From 932a3fe941e5472a1be323605a244c8ccb835129 Mon Sep 17 00:00:00 2001 From: David Viejo Date: Mon, 3 Aug 2026 09:26:44 +0200 Subject: [PATCH 01/12] feat(flags): add feature flag entities and migration Two tables mirroring the env_vars/env_var_environments split: the definition is project-scoped, the value is overridden per environment. Three columns ship without a Phase 1 reader because each is expensive or impossible to introduce correctly later: - salt: percentage bucketing must be stable from the first rollout, so a salt added after subjects are assigned would reshuffle every live experiment - client_visible: defaults to false; flipping a security default later would expose server-only flags that predate the change - rules: the evaluator reserves an ordered targeting step between the kill switch and the environment value, so writing rules later cannot change what an existing flag serves salt is #[serde(skip_serializing)] so it cannot leak even if the entity is ever returned directly - a published salt lets a client pre-compute its own bucket and self-select into a rollout. Includes an up/down/up reversibility test: the tables are FK-linked, so dropping them in the wrong order fails, and a half-applied rollback would leave an operator unable to migrate forward. --- .../src/feature_flag_environments.rs | 84 ++++++ crates/temps-entities/src/feature_flags.rs | 106 +++++++ crates/temps-entities/src/lib.rs | 2 + .../m20260802_000002_create_feature_flags.rs | 272 ++++++++++++++++++ crates/temps-migrations/src/migration/mod.rs | 2 + .../temps-migrations/tests/migration_tests.rs | 105 +++++++ 6 files changed, 571 insertions(+) create mode 100644 crates/temps-entities/src/feature_flag_environments.rs create mode 100644 crates/temps-entities/src/feature_flags.rs create mode 100644 crates/temps-migrations/src/migration/m20260802_000002_create_feature_flags.rs diff --git a/crates/temps-entities/src/feature_flag_environments.rs b/crates/temps-entities/src/feature_flag_environments.rs new file mode 100644 index 000000000..22f65a947 --- /dev/null +++ b/crates/temps-entities/src/feature_flag_environments.rs @@ -0,0 +1,84 @@ +//! `SeaORM` Entity for the `feature_flag_environments` table. +//! +//! Per-environment override of a [`super::feature_flags`] definition. One row +//! per (flag, environment); a missing row means "inherit the flag default". +//! +//! `rules` ships in Phase 1 as a column that is always `[]`. The evaluator +//! reserves a step for it between the kill switch and the environment value, +//! so populating it later cannot change what an existing flag serves. + +use async_trait::async_trait; +use sea_orm::entity::prelude::*; +use sea_orm::{ActiveValue::Set, ConnectionTrait, DbErr}; +use serde::{Deserialize, Serialize}; +use temps_core::DBDateTime; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "feature_flag_environments")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub flag_id: i32, + pub environment_id: i32, + /// The kill switch. When false, evaluation short-circuits to the flag's + /// default value *before* any targeting is consulted — so this keeps + /// meaning exactly "ignore everything, serve the default" once rules exist. + pub enabled: bool, + /// Environment-specific value. NULL means inherit `feature_flags.default_value`. + pub value: Option, + /// Ordered targeting rules. Always `[]` in Phase 1. + pub rules: Json, + pub created_at: DBDateTime, + pub updated_at: DBDateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::feature_flags::Entity", + from = "Column::FlagId", + to = "super::feature_flags::Column::Id" + )] + FeatureFlag, + #[sea_orm( + belongs_to = "super::environments::Entity", + from = "Column::EnvironmentId", + to = "super::environments::Column::Id" + )] + Environment, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FeatureFlag.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Environment.def() + } +} + +#[async_trait] +impl ActiveModelBehavior for ActiveModel { + async fn before_save(mut self, _db: &C, insert: bool) -> Result + where + C: ConnectionTrait, + { + let now = chrono::Utc::now(); + + if insert { + if self.created_at.is_not_set() { + self.created_at = Set(now); + } + if self.updated_at.is_not_set() { + self.updated_at = Set(now); + } + } else { + self.updated_at = Set(now); + } + + Ok(self) + } +} diff --git a/crates/temps-entities/src/feature_flags.rs b/crates/temps-entities/src/feature_flags.rs new file mode 100644 index 000000000..c77c12092 --- /dev/null +++ b/crates/temps-entities/src/feature_flags.rs @@ -0,0 +1,106 @@ +//! `SeaORM` Entity for the `feature_flags` table. +//! +//! A feature flag is defined once per project and its value is overridden per +//! environment (see [`super::feature_flag_environments`]). This mirrors the +//! `env_vars` / `env_var_environments` split. +//! +//! Two columns exist in Phase 1 but are deliberately unused by the evaluator: +//! +//! - `salt` is generated at create time so percentage bucketing is stable from +//! the very first rollout. Introducing it later would reshuffle every user +//! already assigned to a variant. +//! - `client_visible` defaults to `false` so flags are server-only unless the +//! operator opts in. Flipping a security default after the fact would expose +//! flags that were never meant to leave the server. + +use async_trait::async_trait; +use sea_orm::entity::prelude::*; +use sea_orm::{ActiveValue::Set, ConnectionTrait, DbErr}; +use serde::{Deserialize, Serialize}; +use temps_core::DBDateTime; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "feature_flags")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub project_id: i32, + /// Stable identifier used in application code. Immutable after create: + /// keys leak into user source and (later) analytics dimensions. + pub key: String, + /// One of `bool`, `string`, `number`, `json`. Fixed at create — retyping + /// would break both stored data and user code. + pub value_type: String, + /// Served whenever evaluation cannot do better. Never SQL NULL. + pub default_value: Json, + pub description: Option, + /// Per-flag bucketing salt. Rotating it reshuffles the rollout cohort. + /// Populated at create; not read until targeting ships. + /// + /// Never serialized. Every response DTO omits it by hand today, but that is + /// convention rather than enforcement — publishing the salt would let a + /// client pre-compute `bucket(key, salt, subject)` and self-select into or + /// out of a percentage rollout. `skip_serializing` makes that durable if + /// this entity is ever returned directly. + #[serde(skip_serializing)] + pub salt: String, + /// When false (the default) the flag is never exposed on the + /// unauthenticated same-origin evaluation endpoint. + pub client_visible: bool, + /// Soft delete. Archived flags evaluate as `FLAG_NOT_FOUND` so callers + /// fall back to their own default rather than silently changing behaviour. + pub archived_at: Option, + pub created_at: DBDateTime, + pub updated_at: DBDateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::projects::Entity", + from = "Column::ProjectId", + to = "super::projects::Column::Id" + )] + Project, + #[sea_orm( + has_many = "super::feature_flag_environments::Entity", + from = "Column::Id", + to = "super::feature_flag_environments::Column::FlagId" + )] + FeatureFlagEnvironments, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Project.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FeatureFlagEnvironments.def() + } +} + +#[async_trait] +impl ActiveModelBehavior for ActiveModel { + async fn before_save(mut self, _db: &C, insert: bool) -> Result + where + C: ConnectionTrait, + { + let now = chrono::Utc::now(); + + if insert { + if self.created_at.is_not_set() { + self.created_at = Set(now); + } + if self.updated_at.is_not_set() { + self.updated_at = Set(now); + } + } else { + self.updated_at = Set(now); + } + + Ok(self) + } +} diff --git a/crates/temps-entities/src/lib.rs b/crates/temps-entities/src/lib.rs index d61e4ff1a..7477ed0b4 100644 --- a/crates/temps-entities/src/lib.rs +++ b/crates/temps-entities/src/lib.rs @@ -54,6 +54,8 @@ pub mod external_images; pub mod external_service_backups; pub mod external_service_health_checks; pub mod external_services; +pub mod feature_flag_environments; +pub mod feature_flags; pub mod funnel_steps; pub mod funnels; pub mod git_provider_connections; diff --git a/crates/temps-migrations/src/migration/m20260802_000002_create_feature_flags.rs b/crates/temps-migrations/src/migration/m20260802_000002_create_feature_flags.rs new file mode 100644 index 000000000..e937c043d --- /dev/null +++ b/crates/temps-migrations/src/migration/m20260802_000002_create_feature_flags.rs @@ -0,0 +1,272 @@ +//! Creates the feature-flag tables (ADR-034, Phase 1). +//! +//! Two tables, mirroring the `env_vars` / `env_var_environments` split: the +//! definition is project-scoped, the value is overridden per environment. +//! +//! Three columns land here without a Phase 1 reader, on purpose — each is +//! expensive or impossible to introduce correctly later: +//! +//! - `feature_flags.salt`: percentage bucketing must be stable from the first +//! rollout. A salt added after users are already assigned reshuffles them. +//! - `feature_flags.client_visible`: defaults to `false`. Flipping a security +//! default later would expose server-only flags that predate the change. +//! - `feature_flag_environments.rules`: the evaluator already reserves an +//! ordered step for targeting between the kill switch and the environment +//! value, so writing rules later cannot change what an existing flag serves. + +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(FeatureFlags::Table) + .if_not_exists() + .col( + ColumnDef::new(FeatureFlags::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(FeatureFlags::ProjectId).integer().not_null()) + .col(ColumnDef::new(FeatureFlags::Key).string_len(128).not_null()) + .col( + ColumnDef::new(FeatureFlags::ValueType) + .string_len(16) + .not_null(), + ) + .col( + ColumnDef::new(FeatureFlags::DefaultValue) + .json_binary() + .not_null(), + ) + .col( + ColumnDef::new(FeatureFlags::Description) + .string_len(512) + .null(), + ) + .col(ColumnDef::new(FeatureFlags::Salt).string_len(32).not_null()) + .col( + ColumnDef::new(FeatureFlags::ClientVisible) + .boolean() + .not_null() + .default(false), + ) + .col( + ColumnDef::new(FeatureFlags::ArchivedAt) + .timestamp_with_time_zone() + .null(), + ) + .col( + ColumnDef::new(FeatureFlags::CreatedAt) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .col( + ColumnDef::new(FeatureFlags::UpdatedAt) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .to_owned(), + ) + .await?; + + manager + .create_foreign_key( + ForeignKey::create() + .name("fk_feature_flags_project") + .from(FeatureFlags::Table, FeatureFlags::ProjectId) + .to(Projects::Table, Projects::Id) + .on_delete(ForeignKeyAction::Cascade) + .to_owned(), + ) + .await?; + + // Flag keys are unique per project and immutable after create. + manager + .create_index( + Index::create() + .name("idx_feature_flags_project_key") + .table(FeatureFlags::Table) + .col(FeatureFlags::ProjectId) + .col(FeatureFlags::Key) + .unique() + .to_owned(), + ) + .await?; + + manager + .create_table( + Table::create() + .table(FeatureFlagEnvironments::Table) + .if_not_exists() + .col( + ColumnDef::new(FeatureFlagEnvironments::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col( + ColumnDef::new(FeatureFlagEnvironments::FlagId) + .integer() + .not_null(), + ) + .col( + ColumnDef::new(FeatureFlagEnvironments::EnvironmentId) + .integer() + .not_null(), + ) + .col( + ColumnDef::new(FeatureFlagEnvironments::Enabled) + .boolean() + .not_null() + .default(true), + ) + .col( + ColumnDef::new(FeatureFlagEnvironments::Value) + .json_binary() + .null(), + ) + .col( + ColumnDef::new(FeatureFlagEnvironments::Rules) + .json_binary() + .not_null() + .default(Expr::cust("'[]'::jsonb")), + ) + .col( + ColumnDef::new(FeatureFlagEnvironments::CreatedAt) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .col( + ColumnDef::new(FeatureFlagEnvironments::UpdatedAt) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .to_owned(), + ) + .await?; + + manager + .create_foreign_key( + ForeignKey::create() + .name("fk_feature_flag_environments_flag") + .from( + FeatureFlagEnvironments::Table, + FeatureFlagEnvironments::FlagId, + ) + .to(FeatureFlags::Table, FeatureFlags::Id) + .on_delete(ForeignKeyAction::Cascade) + .to_owned(), + ) + .await?; + + manager + .create_foreign_key( + ForeignKey::create() + .name("fk_feature_flag_environments_environment") + .from( + FeatureFlagEnvironments::Table, + FeatureFlagEnvironments::EnvironmentId, + ) + .to(Environments::Table, Environments::Id) + .on_delete(ForeignKeyAction::Cascade) + .to_owned(), + ) + .await?; + + // One override row per (flag, environment). + manager + .create_index( + Index::create() + .name("idx_feature_flag_environments_flag_env") + .table(FeatureFlagEnvironments::Table) + .col(FeatureFlagEnvironments::FlagId) + .col(FeatureFlagEnvironments::EnvironmentId) + .unique() + .to_owned(), + ) + .await?; + + // Snapshot endpoint reads every override for one environment. + manager + .create_index( + Index::create() + .name("idx_feature_flag_environments_environment") + .table(FeatureFlagEnvironments::Table) + .col(FeatureFlagEnvironments::EnvironmentId) + .to_owned(), + ) + .await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table( + Table::drop() + .table(FeatureFlagEnvironments::Table) + .to_owned(), + ) + .await?; + + manager + .drop_table(Table::drop().table(FeatureFlags::Table).to_owned()) + .await?; + + Ok(()) + } +} + +#[derive(DeriveIden)] +enum FeatureFlags { + Table, + Id, + ProjectId, + Key, + ValueType, + DefaultValue, + Description, + Salt, + ClientVisible, + ArchivedAt, + CreatedAt, + UpdatedAt, +} + +#[derive(DeriveIden)] +enum FeatureFlagEnvironments { + Table, + Id, + FlagId, + EnvironmentId, + Enabled, + Value, + Rules, + CreatedAt, + UpdatedAt, +} + +#[derive(DeriveIden)] +enum Projects { + Table, + Id, +} + +#[derive(DeriveIden)] +enum Environments { + Table, + Id, +} diff --git a/crates/temps-migrations/src/migration/mod.rs b/crates/temps-migrations/src/migration/mod.rs index 96602e424..deb46527c 100644 --- a/crates/temps-migrations/src/migration/mod.rs +++ b/crates/temps-migrations/src/migration/mod.rs @@ -166,6 +166,7 @@ mod m20260725_000001_sandboxes_agent_run_link; mod m20260728_000001_add_environment_id_to_metric_alert_rules; mod m20260730_000001_add_architecture_to_nodes; mod m20260802_000001_add_environment_force_https; +mod m20260802_000002_create_feature_flags; pub struct Migrator; @@ -339,6 +340,7 @@ impl MigratorTrait for Migrator { ), Box::new(m20260730_000001_add_architecture_to_nodes::Migration), Box::new(m20260802_000001_add_environment_force_https::Migration), + Box::new(m20260802_000002_create_feature_flags::Migration), ] } } diff --git a/crates/temps-migrations/tests/migration_tests.rs b/crates/temps-migrations/tests/migration_tests.rs index 108f605c7..524cb6acb 100644 --- a/crates/temps-migrations/tests/migration_tests.rs +++ b/crates/temps-migrations/tests/migration_tests.rs @@ -2182,3 +2182,108 @@ async fn test_mfa_pending_migration_revokes_ambiguous_sessions_and_defaults_clos Ok(()) } + +/// The feature-flag migration must be reversible: `down` drops the child table +/// before the parent, and a re-`up` must rebuild the exact schema. +/// +/// Worth a dedicated test because the two tables are linked by a foreign key, +/// so dropping them in the wrong order fails, and because a half-applied +/// rollback would leave an operator unable to migrate forward again. +#[tokio::test] +async fn test_feature_flags_migration_is_reversible() -> anyhow::Result<()> { + if external_db_configured() { + return Ok(()); + } + + let container = match GenericImage::new("timescale/timescaledb-ha", "pg18") + .with_env_var("POSTGRES_DB", "postgres") + .with_env_var("POSTGRES_USER", "postgres") + .with_env_var("POSTGRES_PASSWORD", "postgres") + .with_env_var("POSTGRES_HOST_AUTH_METHOD", "trust") + .with_cmd(vec![ + "postgres", + "-c", + "timescaledb.max_background_workers=0", + ]) + .start() + .await + { + Ok(container) => container, + Err(error) => { + eprintln!("Skipping feature-flag migration test: Docker unavailable: {error}"); + return Ok(()); + } + }; + + let port = container.get_host_port_ipv4(5432).await?; + let db_url = format!("postgresql://postgres:postgres@localhost:{port}/postgres"); + tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; + let db = connect_with_retries(&db_url).await?; + + Migrator::up(&db, None).await?; + assert_eq!( + feature_flag_table_count(&db).await?, + 2, + "both feature-flag tables must exist after `up`" + ); + + // Roll back exactly through the feature-flag migration, wherever it sits + // in the chain — a hardcoded step count breaks the moment a newer + // migration lands after it. + let target = "m20260802_000002_create_feature_flags"; + let after = db + .query_one(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + format!("SELECT count(*)::int AS n FROM seaql_migrations WHERE version > '{target}'"), + )) + .await? + .expect("seaql_migrations count"); + let steps_after: i32 = after.try_get("", "n")?; + + Migrator::down(&db, Some(steps_after as u32 + 1)).await?; + assert_eq!( + feature_flag_table_count(&db).await?, + 0, + "`down` must drop both tables, child before parent" + ); + + // Forward again: an operator who rolled back must be able to upgrade. + Migrator::up(&db, None).await?; + assert_eq!( + feature_flag_table_count(&db).await?, + 2, + "re-running `up` after a rollback must rebuild both tables" + ); + + // The column that was deliberately dropped from the design must not + // reappear: it could only ever have been NULL, and surfacing an + // always-empty "last evaluated" would invite deleting a live flag. + let stale_column = db + .query_one(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + "SELECT count(*)::int AS n FROM information_schema.columns \ + WHERE table_name = 'feature_flag_environments' \ + AND column_name = 'last_evaluated_at'" + .to_string(), + )) + .await? + .expect("column count"); + let stale: i32 = stale_column.try_get("", "n")?; + assert_eq!(stale, 0, "last_evaluated_at must not exist"); + + Ok(()) +} + +async fn feature_flag_table_count(db: &DatabaseConnection) -> anyhow::Result { + let row = db + .query_one(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + "SELECT count(*)::int AS n FROM information_schema.tables \ + WHERE table_schema = 'public' \ + AND table_name IN ('feature_flags', 'feature_flag_environments')" + .to_string(), + )) + .await? + .expect("table count"); + Ok(row.try_get("", "n")?) +} From d96192a625085360f5584470d8d957e9721938e3 Mon Sep 17 00:00:00 2001 From: David Viejo Date: Mon, 3 Aug 2026 09:31:07 +0200 Subject: [PATCH 02/12] feat(flags): add temps-flags crate with evaluation, API and RBAC Phase 1 of ADR-034: set a flag value per environment and flip it without a redeploy. No targeting rules yet, but the parts that are expensive to change once callers depend on them are fixed now. Resolution order is pinned, with a reserved step for targeting: 1. flag missing/archived -> caller's fallback FLAG_NOT_FOUND 2. enabled == false -> default_value DISABLED 3. -- reserved for rules -- 4. environment value set -> that value ENVIRONMENT_VALUE 5. otherwise -> default_value DEFAULT Deciding later whether a rule outranks a blanket per-environment value would silently change what existing flags serve, so it is decided now. The kill switch short-circuits ahead of targeting, so `enabled = false` keeps meaning exactly "ignore everything, serve the default" once rules land. evaluate() is pure, synchronous and total: it returns a usable value for every input and never panics. A stored value that no longer matches the flag's type degrades to the default rather than failing the caller's request. bucket() ships tested but uncalled. Once one subject is inside a percentage rollout the algorithm can never change, so it is pinned with locked vectors before anything can depend on it. Security: - Every project-scoped handler carries project_scope_guard! and project_access_guard!. The latter deliberately skips deployment tokens and delegates their confinement to the former; shipping only one left a cross-project IDOR where a token for project A could read project B's flags. Four regression tests fail if the guard is removed. - Deployment tokens are read-only: Permission::FlagsRead bridges to DeploymentTokenPermission::FlagsRead, FlagsWrite/FlagsDelete deliberately do not. A credential baked into a container must not flip a production flag. - The snapshot endpoint takes its scope from the token, never a path parameter, and returns one error for both "no such environment" and "another project's environment" so it cannot be used as an existence oracle. - Audit entries record old and new values on every mutation. A flag change is a production change with no deployment behind it, so the audit log is the only record it happened. List is paginated (default 20, max 100). The clamp is shared with the handler so total_pages cannot describe a page size the server did not serve. The snapshot endpoint is deliberately unpaginated: the SDK needs the whole set. --- Cargo.lock | 24 + Cargo.toml | 1 + crates/temps-auth/src/context.rs | 6 + crates/temps-auth/src/permission_guard.rs | 1 + crates/temps-auth/src/permissions.rs | 23 + crates/temps-cli/Cargo.toml | 1 + .../temps-cli/src/commands/serve/console.rs | 7 + .../temps-entities/src/deployment_tokens.rs | 5 + crates/temps-flags/Cargo.toml | 45 + crates/temps-flags/src/error.rs | 49 + crates/temps-flags/src/eval.rs | 448 ++++++++ crates/temps-flags/src/handlers/audit.rs | 91 ++ crates/temps-flags/src/handlers/handler.rs | 1016 +++++++++++++++++ crates/temps-flags/src/handlers/mod.rs | 6 + crates/temps-flags/src/handlers/types.rs | 201 ++++ crates/temps-flags/src/lib.rs | 27 + crates/temps-flags/src/plugin.rs | 74 ++ .../temps-flags/src/services/flag_service.rs | 955 ++++++++++++++++ crates/temps-flags/src/services/mod.rs | 6 + 19 files changed, 2986 insertions(+) create mode 100644 crates/temps-flags/Cargo.toml create mode 100644 crates/temps-flags/src/error.rs create mode 100644 crates/temps-flags/src/eval.rs create mode 100644 crates/temps-flags/src/handlers/audit.rs create mode 100644 crates/temps-flags/src/handlers/handler.rs create mode 100644 crates/temps-flags/src/handlers/mod.rs create mode 100644 crates/temps-flags/src/handlers/types.rs create mode 100644 crates/temps-flags/src/lib.rs create mode 100644 crates/temps-flags/src/plugin.rs create mode 100644 crates/temps-flags/src/services/flag_service.rs create mode 100644 crates/temps-flags/src/services/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 2c0b23e67..8d0f7b00f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11094,6 +11094,7 @@ dependencies = [ "temps-environments", "temps-error-tracking", "temps-external-plugins", + "temps-flags", "temps-geo", "temps-git", "temps-import", @@ -11735,6 +11736,29 @@ dependencies = [ "uuid", ] +[[package]] +name = "temps-flags" +version = "0.1.0-beta.55" +dependencies = [ + "anyhow", + "async-trait", + "axum", + "chrono", + "hex", + "sea-orm", + "serde", + "serde_json", + "sha2 0.11.0", + "temps-auth", + "temps-core", + "temps-entities", + "thiserror 2.0.18", + "tokio", + "tracing", + "utoipa", + "uuid", +] + [[package]] name = "temps-geo" version = "0.1.0-beta.55" diff --git a/Cargo.toml b/Cargo.toml index 6addb8a9f..86ab68a18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ members = [ "crates/temps-dns-resolver", "crates/temps-vulnerability-scanner", "crates/temps-kv", + "crates/temps-flags", "crates/temps-blob", "crates/temps-log-aggregator", "crates/temps-otel", diff --git a/crates/temps-auth/src/context.rs b/crates/temps-auth/src/context.rs index e3e59a989..c70e561dc 100644 --- a/crates/temps-auth/src/context.rs +++ b/crates/temps-auth/src/context.rs @@ -190,6 +190,12 @@ impl AuthContext { // (POST /ai/v1/chat/completions, guarded by AiGatewayExecute). // Same documented machine-access pattern as EmailsSend. Permission::AiGatewayExecute => DeploymentTokenPermission::AiGatewayExecute, + // Deployed apps read their own environment's feature-flag + // snapshot with TEMPS_API_TOKEN. Read-only: a machine + // credential baked into a container must never be able to + // flip a flag in production, so FlagsWrite/FlagsDelete are + // deliberately absent from this bridge. + Permission::FlagsRead => DeploymentTokenPermission::FlagsRead, // No implicit bridge from deployment-token permissions to // general control-plane permissions. _ => return false, diff --git a/crates/temps-auth/src/permission_guard.rs b/crates/temps-auth/src/permission_guard.rs index 8b1d810b5..7f59cf9cb 100644 --- a/crates/temps-auth/src/permission_guard.rs +++ b/crates/temps-auth/src/permission_guard.rs @@ -971,6 +971,7 @@ mod tests { "temps-deployments", "temps-environments", "temps-error-tracking", + "temps-flags", "temps-kv", "temps-log-aggregator", "temps-monitoring", diff --git a/crates/temps-auth/src/permissions.rs b/crates/temps-auth/src/permissions.rs index 3880d2991..40fa57463 100644 --- a/crates/temps-auth/src/permissions.rs +++ b/crates/temps-auth/src/permissions.rs @@ -203,6 +203,11 @@ pub enum Permission { KvWrite, KvDelete, + // Feature flag permissions + FlagsRead, + FlagsWrite, + FlagsDelete, + // Status Page permissions StatusPageRead, StatusPageWrite, @@ -358,6 +363,9 @@ impl fmt::Display for Permission { Permission::KvRead => "kv:read", Permission::KvWrite => "kv:write", Permission::KvDelete => "kv:delete", + Permission::FlagsRead => "flags:read", + Permission::FlagsWrite => "flags:write", + Permission::FlagsDelete => "flags:delete", Permission::StatusPageRead => "status_page:read", Permission::StatusPageWrite => "status_page:write", Permission::StatusPageCreate => "status_page:create", @@ -504,6 +512,9 @@ impl Permission { "kv:read" => Some(Permission::KvRead), "kv:write" => Some(Permission::KvWrite), "kv:delete" => Some(Permission::KvDelete), + "flags:read" => Some(Permission::FlagsRead), + "flags:write" => Some(Permission::FlagsWrite), + "flags:delete" => Some(Permission::FlagsDelete), "status_page:read" => Some(Permission::StatusPageRead), "status_page:write" => Some(Permission::StatusPageWrite), "status_page:create" => Some(Permission::StatusPageCreate), @@ -647,6 +658,9 @@ impl Permission { Permission::KvRead, Permission::KvWrite, Permission::KvDelete, + Permission::FlagsRead, + Permission::FlagsWrite, + Permission::FlagsDelete, Permission::StatusPageRead, Permission::StatusPageWrite, Permission::StatusPageCreate, @@ -848,6 +862,9 @@ impl Role { Permission::KvRead, Permission::KvWrite, Permission::KvDelete, + Permission::FlagsRead, + Permission::FlagsWrite, + Permission::FlagsDelete, Permission::StatusPageRead, Permission::StatusPageWrite, Permission::StatusPageCreate, @@ -983,6 +1000,9 @@ impl Role { Permission::KvRead, Permission::KvWrite, Permission::KvDelete, + Permission::FlagsRead, + Permission::FlagsWrite, + Permission::FlagsDelete, Permission::StatusPageRead, Permission::StatusPageWrite, Permission::StatusPageCreate, @@ -1090,6 +1110,8 @@ impl Role { Permission::BlobWrite, Permission::KvRead, Permission::KvWrite, + Permission::FlagsRead, + Permission::FlagsWrite, Permission::StatusPageRead, Permission::StatusPageWrite, Permission::StatusPageCreate, @@ -1138,6 +1160,7 @@ impl Role { Permission::VulnerabilityScansRead, Permission::BlobRead, Permission::KvRead, + Permission::FlagsRead, Permission::StatusPageRead, Permission::OtelRead, Permission::AiGatewayRead, diff --git a/crates/temps-cli/Cargo.toml b/crates/temps-cli/Cargo.toml index 845a710aa..7a56b7302 100644 --- a/crates/temps-cli/Cargo.toml +++ b/crates/temps-cli/Cargo.toml @@ -29,6 +29,7 @@ temps-analytics = { path = "../temps-analytics" } temps-analytics-events = { path = "../temps-analytics-events" } temps-blob = { path = "../temps-blob" } temps-kv = { path = "../temps-kv" } +temps-flags = { path = "../temps-flags" } temps-analytics-funnels = { path = "../temps-analytics-funnels" } temps-analytics-performance = { path = "../temps-analytics-performance" } temps-analytics-session-replay = { path = "../temps-analytics-session-replay" } diff --git a/crates/temps-cli/src/commands/serve/console.rs b/crates/temps-cli/src/commands/serve/console.rs index 696106621..46a327287 100644 --- a/crates/temps-cli/src/commands/serve/console.rs +++ b/crates/temps-cli/src/commands/serve/console.rs @@ -41,6 +41,7 @@ use temps_email::EmailPlugin; use temps_entities::users; use temps_environments::EnvironmentsPlugin; use temps_error_tracking::ErrorTrackingPlugin; +use temps_flags::FlagsPlugin; use temps_geo::GeoPlugin; use temps_git::GitPlugin; use temps_import::ImportPlugin; @@ -1881,6 +1882,12 @@ pub async fn start_console_api(params: ConsoleApiParams) -> anyhow::Result<()> { let blob_plugin = Box::new(BlobPlugin::new()); plugin_manager.register_plugin(blob_plugin); + // 5.3. FlagsPlugin - provides feature flags (depends on database only: + // flags are control-plane rows, no container and no background task) + debug!("Registering FlagsPlugin"); + let flags_plugin = Box::new(FlagsPlugin::new()); + plugin_manager.register_plugin(flags_plugin); + // 5.5. EnvironmentsPlugin - provides environment management (depends on config) debug!("Registering EnvironmentsPlugin"); let environments_plugin = Box::new(EnvironmentsPlugin::new()); diff --git a/crates/temps-entities/src/deployment_tokens.rs b/crates/temps-entities/src/deployment_tokens.rs index a9f173a4c..c4603219d 100644 --- a/crates/temps-entities/src/deployment_tokens.rs +++ b/crates/temps-entities/src/deployment_tokens.rs @@ -136,6 +136,8 @@ pub enum DeploymentTokenPermission { ErrorsRead, /// Execute AI gateway requests (chat completions, embeddings) AiGatewayExecute, + /// Read feature-flag snapshots for the token's environment + FlagsRead, /// Full access (all permissions) FullAccess, } @@ -150,6 +152,7 @@ impl DeploymentTokenPermission { DeploymentTokenPermission::EventsWrite => "events:write", DeploymentTokenPermission::ErrorsRead => "errors:read", DeploymentTokenPermission::AiGatewayExecute => "ai_gateway:execute", + DeploymentTokenPermission::FlagsRead => "flags:read", DeploymentTokenPermission::FullAccess => "*", } } @@ -164,6 +167,7 @@ impl DeploymentTokenPermission { "events:write" => Some(DeploymentTokenPermission::EventsWrite), "errors:read" => Some(DeploymentTokenPermission::ErrorsRead), "ai_gateway:execute" => Some(DeploymentTokenPermission::AiGatewayExecute), + "flags:read" => Some(DeploymentTokenPermission::FlagsRead), "*" | "full_access" => Some(DeploymentTokenPermission::FullAccess), _ => None, } @@ -178,6 +182,7 @@ impl DeploymentTokenPermission { DeploymentTokenPermission::EventsWrite, DeploymentTokenPermission::ErrorsRead, DeploymentTokenPermission::AiGatewayExecute, + DeploymentTokenPermission::FlagsRead, DeploymentTokenPermission::FullAccess, ] } diff --git a/crates/temps-flags/Cargo.toml b/crates/temps-flags/Cargo.toml new file mode 100644 index 000000000..169128416 --- /dev/null +++ b/crates/temps-flags/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "temps-flags" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +# Internal crates +temps-core = { path = "../temps-core" } +temps-auth = { path = "../temps-auth" } +temps-entities = { path = "../temps-entities" } + +# Async runtime +tokio.workspace = true +async-trait.workspace = true + +# Web framework +axum.workspace = true + +# Serialization +serde.workspace = true +serde_json.workspace = true + +# Error handling & logging +anyhow.workspace = true +thiserror.workspace = true +tracing.workspace = true + +# Date/Time & IDs +chrono.workspace = true +uuid.workspace = true + +# API Documentation +utoipa.workspace = true + +# Data access +sea-orm.workspace = true + +# Bucketing hash + ETag +sha2.workspace = true +hex.workspace = true + +[dev-dependencies] +tokio = { workspace = true, features = ["test-util", "macros"] } diff --git a/crates/temps-flags/src/error.rs b/crates/temps-flags/src/error.rs new file mode 100644 index 000000000..3f030397e --- /dev/null +++ b/crates/temps-flags/src/error.rs @@ -0,0 +1,49 @@ +//! Typed errors for the feature-flag domain. + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum FlagError { + #[error("Feature flag '{key}' not found in project {project_id}")] + NotFound { project_id: i32, key: String }, + + #[error("Feature flag '{key}' already exists in project {project_id}")] + DuplicateKey { project_id: i32, key: String }, + + #[error("Environment {environment_id} does not belong to project {project_id}")] + EnvironmentNotInProject { + project_id: i32, + environment_id: i32, + }, + + #[error("Environment {environment_id} not found")] + EnvironmentNotFound { environment_id: i32 }, + + #[error( + "Invalid flag key '{key}': {reason}. Keys must match [a-z0-9][a-z0-9._-]* and be at most 128 characters" + )] + InvalidKey { key: String, reason: String }, + + #[error("Invalid value type '{value_type}' for flag '{key}': must be one of bool, string, number, json")] + InvalidValueType { key: String, value_type: String }, + + #[error("Value {value} is not valid for flag '{key}' of type '{value_type}' (field: {field})")] + ValueTypeMismatch { + key: String, + value_type: String, + value: String, + field: String, + }, + + #[error("Validation error for flag '{key}': {message}")] + Validation { key: String, message: String }, + + #[error("Deployment token for project {project_id} is not scoped to a single environment; feature-flag snapshots require an environment-scoped token")] + TokenNotEnvironmentScoped { project_id: i32 }, + + #[error("Database error: {0}")] + Database(#[from] sea_orm::DbErr), + + #[error("Failed to serialize flag value for flag '{key}': {reason}")] + Serialization { key: String, reason: String }, +} diff --git a/crates/temps-flags/src/eval.rs b/crates/temps-flags/src/eval.rs new file mode 100644 index 000000000..9a90e26c0 --- /dev/null +++ b/crates/temps-flags/src/eval.rs @@ -0,0 +1,448 @@ +//! Flag evaluation: a pure, synchronous, total function. +//! +//! No database, no I/O, no `async`. That is what lets the same code run in an +//! HTTP handler, inside the SDK, and (later) on the proxy hot path. +//! +//! # Resolution order +//! +//! ```text +//! 1. flag missing or archived -> caller's fallback FLAG_NOT_FOUND +//! 2. enabled == false -> default_value DISABLED +//! 3. -- reserved for rules -- RULE_MATCH{i} +//! | PERCENTAGE_ROLLOUT{i} +//! 4. environment value present -> that value ENVIRONMENT_VALUE +//! 5. otherwise -> default_value DEFAULT +//! ``` +//! +//! Step 3 is unreachable in Phase 1 because no rules are ever stored. The order +//! is fixed now on purpose: deciding later whether a rule outranks a blanket +//! per-environment value would silently change what existing flags serve. +//! +//! Two consequences worth keeping: +//! +//! - Rules beat the environment value, because a rule is the more specific +//! statement. +//! - The kill switch outranks everything. `enabled = false` short-circuits +//! before targeting is consulted, so it keeps meaning exactly "ignore all +//! targeting, everyone gets the default" once rules exist. + +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; +use utoipa::ToSchema; + +/// The declared type of a flag's value. Fixed at create time. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)] +#[serde(rename_all = "lowercase")] +pub enum FlagValueType { + Bool, + String, + Number, + Json, +} + +impl FlagValueType { + pub fn as_str(&self) -> &'static str { + match self { + FlagValueType::Bool => "bool", + FlagValueType::String => "string", + FlagValueType::Number => "number", + FlagValueType::Json => "json", + } + } + + pub fn parse(raw: &str) -> Option { + match raw { + "bool" => Some(FlagValueType::Bool), + "string" => Some(FlagValueType::String), + "number" => Some(FlagValueType::Number), + "json" => Some(FlagValueType::Json), + _ => None, + } + } + + /// Whether a concrete JSON value is admissible for this declared type. + /// + /// `Json` accepts anything except `null`: a flag must always resolve to a + /// usable value, and `null` is indistinguishable from "unset" downstream. + pub fn matches(&self, value: &serde_json::Value) -> bool { + match self { + FlagValueType::Bool => value.is_boolean(), + FlagValueType::String => value.is_string(), + FlagValueType::Number => value.is_number(), + FlagValueType::Json => !value.is_null(), + } + } +} + +/// Why an evaluation produced the value it did. +/// +/// Part of the wire contract, and the only thing that makes "why is this user +/// seeing the old checkout?" answerable. `RuleMatch` and `PercentageRollout` +/// are declared now but never produced until targeting ships. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)] +#[serde(tag = "kind", rename_all = "SCREAMING_SNAKE_CASE")] +pub enum EvalReason { + /// No such flag, or it has been archived. The caller's fallback is served. + FlagNotFound, + /// Kill switch engaged for this environment. + Disabled, + /// A targeting rule matched. Reserved; not produced in Phase 1. + RuleMatch { index: usize }, + /// A percentage rollout included this subject. Reserved; not produced in + /// Phase 1. + PercentageRollout { index: usize }, + /// An environment-specific value was set. + EnvironmentValue, + /// Nothing more specific applied; the flag default was served. + Default, + /// Evaluation degraded (malformed stored value). The default is served and + /// the caller is told the value is not trustworthy. Never panics. + Error, +} + +/// A targeting attribute supplied by the caller. +/// +/// Accepted and carried through in Phase 1, but not yet read by [`evaluate`]. +/// The parameter is the expensive part of the contract; the code that consumes +/// it is cheap to add. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum AttributeValue { + Bool(bool), + Number(f64), + String(String), +} + +/// Everything the caller knows about the subject being evaluated. +#[derive(Debug, Clone, Default)] +pub struct EvalContext { + /// Stable bucketing subject (user id, account id, device id). Unused in + /// Phase 1; required for stable percentage rollout later. + pub key: Option, + /// Targeting attributes. Unused in Phase 1. + pub attributes: HashMap, +} + +/// A single flag, already resolved down to one environment. This is what the +/// evaluator sees and what the SDK caches in memory. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)] +pub struct FlagSnapshot { + pub key: String, + pub value_type: FlagValueType, + /// Served whenever evaluation cannot do better. Genuinely polymorphic by + /// design — the surrounding struct carries the type. + pub default_value: serde_json::Value, + /// False means the kill switch is engaged for this environment. + pub enabled: bool, + /// `None` means "inherit `default_value`". + pub environment_value: Option, +} + +/// The outcome of evaluating one flag. Always carries a usable value. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)] +pub struct Evaluation { + pub value: serde_json::Value, + /// Named variant, once variants exist. Always `None` in Phase 1. + pub variant: Option, + pub reason: EvalReason, +} + +impl Evaluation { + fn new(value: &serde_json::Value, reason: EvalReason) -> Self { + Self { + value: value.clone(), + variant: None, + reason, + } + } +} + +/// Evaluate one flag against a context. +/// +/// Total: returns a usable value for every input, never panics, never errors. +/// A malformed stored value degrades to the declared default with +/// [`EvalReason::Error`] rather than failing the caller's request — an app must +/// not break because someone typed the wrong thing into the flag UI. +pub fn evaluate(flag: &FlagSnapshot, _ctx: &EvalContext) -> Evaluation { + if !flag.enabled { + return sanitized(flag, &flag.default_value, EvalReason::Disabled); + } + + // --------------------------------------------------------------------- + // Step 3: targeting rules are evaluated HERE, ahead of the environment + // value and behind the kill switch. Nothing above or below this point + // changes when they land. + // --------------------------------------------------------------------- + + match &flag.environment_value { + Some(value) => sanitized(flag, value, EvalReason::EnvironmentValue), + None => sanitized(flag, &flag.default_value, EvalReason::Default), + } +} + +/// Serve `value` if it matches the flag's declared type, otherwise fall back to +/// the default (and if the default is itself invalid, report `Error`). +fn sanitized(flag: &FlagSnapshot, value: &serde_json::Value, reason: EvalReason) -> Evaluation { + if flag.value_type.matches(value) { + return Evaluation::new(value, reason); + } + if flag.value_type.matches(&flag.default_value) { + return Evaluation::new(&flag.default_value, EvalReason::Error); + } + Evaluation::new(&serde_json::Value::Null, EvalReason::Error) +} + +/// Evaluate a flag that could not be found, using the caller's fallback. +pub fn not_found(fallback: serde_json::Value) -> Evaluation { + Evaluation { + value: fallback, + variant: None, + reason: EvalReason::FlagNotFound, + } +} + +/// Stable percentage bucket in `[0, 100)`. +/// +/// **This function is not called in Phase 1.** It ships early, tested, so the +/// algorithm is pinned before anything can depend on it: once a single user is +/// inside a percentage rollout, changing this silently re-randomizes live +/// experiments. +/// +/// Properties the design relies on, asserted in the tests below: +/// +/// - Widening a rollout never re-rolls anyone already included. +/// - Rotating the salt reshuffles the cohort. +/// - Different flags bucket independently, so the same unlucky subjects are not +/// the guinea pigs for every experiment. +pub fn bucket(flag_key: &str, salt: &str, subject: &str) -> f64 { + let mut hasher = Sha256::new(); + hasher.update(flag_key.as_bytes()); + hasher.update(b":"); + hasher.update(salt.as_bytes()); + hasher.update(b":"); + hasher.update(subject.as_bytes()); + let digest = hasher.finalize(); + + let n = u32::from_be_bytes([digest[0], digest[1], digest[2], digest[3]]); + f64::from(n) / f64::from(u32::MAX) * 100.0 +} + +#[cfg(test)] +mod tests { + use super::*; + + fn snapshot(enabled: bool, env_value: Option) -> FlagSnapshot { + FlagSnapshot { + key: "checkout.v2".to_string(), + value_type: FlagValueType::Bool, + default_value: serde_json::json!(false), + enabled, + environment_value: env_value, + } + } + + #[test] + fn serves_environment_value_when_set() { + let flag = snapshot(true, Some(serde_json::json!(true))); + let result = evaluate(&flag, &EvalContext::default()); + + assert_eq!(result.value, serde_json::json!(true)); + assert_eq!(result.reason, EvalReason::EnvironmentValue); + assert_eq!(result.variant, None); + } + + #[test] + fn falls_back_to_default_when_no_environment_value() { + let flag = snapshot(true, None); + let result = evaluate(&flag, &EvalContext::default()); + + assert_eq!(result.value, serde_json::json!(false)); + assert_eq!(result.reason, EvalReason::Default); + } + + /// The kill switch must outrank the environment value, or "disable this + /// flag" would not actually disable a flag that has an override set. + #[test] + fn kill_switch_beats_environment_value() { + let flag = snapshot(false, Some(serde_json::json!(true))); + let result = evaluate(&flag, &EvalContext::default()); + + assert_eq!(result.value, serde_json::json!(false)); + assert_eq!(result.reason, EvalReason::Disabled); + } + + /// Context is accepted and ignored in Phase 1. Asserting it explicitly so + /// the day targeting lands, this test fails and forces a conscious update. + #[test] + fn context_does_not_affect_evaluation_in_phase_one() { + let flag = snapshot(true, Some(serde_json::json!(true))); + + let mut attributes = HashMap::new(); + attributes.insert("plan".to_string(), AttributeValue::String("free".into())); + let ctx = EvalContext { + key: Some("user_1001".to_string()), + attributes, + }; + + assert_eq!( + evaluate(&flag, &ctx), + evaluate(&flag, &EvalContext::default()) + ); + } + + /// A value that does not match the declared type must not reach the app. + #[test] + fn type_mismatch_degrades_to_default_with_error_reason() { + let mut flag = snapshot(true, Some(serde_json::json!("yes"))); + flag.value_type = FlagValueType::Bool; + + let result = evaluate(&flag, &EvalContext::default()); + + assert_eq!(result.value, serde_json::json!(false)); + assert_eq!(result.reason, EvalReason::Error); + } + + #[test] + fn evaluation_is_total_even_when_default_is_also_invalid() { + let flag = FlagSnapshot { + key: "broken".to_string(), + value_type: FlagValueType::Number, + default_value: serde_json::json!("not a number"), + enabled: true, + environment_value: Some(serde_json::json!("also not a number")), + }; + + let result = evaluate(&flag, &EvalContext::default()); + assert_eq!(result.reason, EvalReason::Error); + } + + #[test] + fn value_type_matching() { + assert!(FlagValueType::Bool.matches(&serde_json::json!(true))); + assert!(!FlagValueType::Bool.matches(&serde_json::json!(1))); + assert!(FlagValueType::Number.matches(&serde_json::json!(1.5))); + assert!(FlagValueType::String.matches(&serde_json::json!("x"))); + assert!(FlagValueType::Json.matches(&serde_json::json!({"a": 1}))); + // null is never a valid flag value: indistinguishable from "unset". + assert!(!FlagValueType::Json.matches(&serde_json::Value::Null)); + } + + // ===================================================================== + // Locked bucketing vectors. + // + // These values are the algorithm's public contract. If a change to + // `bucket()` makes these fail, that change is silently re-randomizing + // every live experiment — fix the change, not the test. + // ===================================================================== + + fn assert_bucket(flag: &str, salt: &str, subject: &str, expected: f64) { + let actual = bucket(flag, salt, subject); + assert!( + (actual - expected).abs() < 0.005, + "bucket({flag}, {salt}, {subject}) = {actual}, expected {expected}" + ); + } + + #[test] + fn bucket_locked_vectors() { + assert_bucket("checkout.v2", "a1b2c3", "user_1001", 36.47); + assert_bucket("checkout.v2", "a1b2c3", "user_1002", 21.03); + assert_bucket("checkout.v2", "a1b2c3", "user_1003", 92.11); + assert_bucket("checkout.v2", "z9y8x7", "user_1003", 8.39); + assert_bucket("new.search", "a1b2c3", "user_1001", 0.33); + } + + #[test] + fn bucket_is_deterministic() { + for _ in 0..100 { + assert_eq!( + bucket("checkout.v2", "a1b2c3", "user_1001"), + bucket("checkout.v2", "a1b2c3", "user_1001") + ); + } + } + + #[test] + fn bucket_is_in_range() { + for i in 0..10_000 { + let b = bucket("checkout.v2", "a1b2c3", &format!("user_{i}")); + assert!((0.0..100.0).contains(&b), "bucket out of range: {b}"); + } + } + + /// Widening a rollout must never remove anyone who was already included. + #[test] + fn ramping_never_re_rolls_an_included_subject() { + for i in 0..2_000 { + let subject = format!("user_{i}"); + let b = bucket("checkout.v2", "a1b2c3", &subject); + + for (lower, upper) in [(10.0, 25.0), (25.0, 50.0), (50.0, 100.0)] { + if b < lower { + assert!( + b < upper, + "subject {subject} was in at {lower}% but out at {upper}%" + ); + } + } + } + } + + #[test] + fn rotating_the_salt_reshuffles_the_cohort() { + let before: Vec = (0..1_000) + .map(|i| bucket("checkout.v2", "a1b2c3", &format!("user_{i}")) < 10.0) + .collect(); + let after: Vec = (0..1_000) + .map(|i| bucket("checkout.v2", "z9y8x7", &format!("user_{i}")) < 10.0) + .collect(); + + let moved = before + .iter() + .zip(after.iter()) + .filter(|(a, b)| a != b) + .count(); + + assert!( + moved > 50, + "salt rotation barely changed the cohort: {moved}" + ); + } + + /// Two flags must not select the same subjects, or the same unlucky users + /// are the guinea pigs for every experiment. + #[test] + fn different_flags_bucket_independently() { + let a: Vec = (0..1_000) + .map(|i| bucket("checkout.v2", "a1b2c3", &format!("user_{i}")) < 20.0) + .collect(); + let b: Vec = (0..1_000) + .map(|i| bucket("new.search", "a1b2c3", &format!("user_{i}")) < 20.0) + .collect(); + + let both = a.iter().zip(b.iter()).filter(|(x, y)| **x && **y).count(); + + // Independent 20% selections overlap ~4% of the time (40 of 1000). + // A correlated implementation would land near 200. + assert!( + (10..=90).contains(&both), + "overlap {both} suggests the two flags are not independent" + ); + } + + /// Distribution sanity: a 25% rollout should land near 25% in aggregate. + #[test] + fn bucket_distributes_evenly() { + let included = (0..20_000) + .filter(|i| bucket("checkout.v2", "a1b2c3", &format!("user_{i}")) < 25.0) + .count(); + + let pct = included as f64 / 20_000.0 * 100.0; + assert!( + (23.0..27.0).contains(&pct), + "25% rollout produced {pct}% inclusion" + ); + } +} diff --git a/crates/temps-flags/src/handlers/audit.rs b/crates/temps-flags/src/handlers/audit.rs new file mode 100644 index 000000000..bd6b722ea --- /dev/null +++ b/crates/temps-flags/src/handlers/audit.rs @@ -0,0 +1,91 @@ +//! Audit events for feature-flag mutations. +//! +//! A flag change is a production change with no deployment record and no code +//! review, so the audit trail is the only place it is written down. Every +//! mutation records the old and new value. + +use anyhow::Result; +use serde::Serialize; +pub use temps_core::AuditContext; +use temps_core::AuditOperation; + +macro_rules! impl_audit_operation { + ($ty:ty, $op:literal) => { + impl AuditOperation for $ty { + fn operation_type(&self) -> String { + $op.to_string() + } + + fn user_id(&self) -> Option { + Some(self.context.user_id) + } + + fn ip_address(&self) -> Option { + self.context.ip_address.clone() + } + + fn user_agent(&self) -> &str { + &self.context.user_agent + } + + fn serialize(&self) -> Result { + serde_json::to_string(self) + .map_err(|e| anyhow::anyhow!("Failed to serialize audit operation: {}", e)) + } + } + }; +} + +#[derive(Debug, Clone, Serialize)] +pub struct FeatureFlagCreatedAudit { + pub context: AuditContext, + pub project_id: i32, + pub flag_id: i32, + pub key: String, + pub value_type: String, + pub default_value: serde_json::Value, + pub client_visible: bool, +} + +#[derive(Debug, Clone, Serialize)] +pub struct FeatureFlagUpdatedAudit { + pub context: AuditContext, + pub project_id: i32, + pub flag_id: i32, + pub key: String, + pub old_default_value: serde_json::Value, + pub new_default_value: serde_json::Value, + pub old_client_visible: bool, + pub new_client_visible: bool, +} + +#[derive(Debug, Clone, Serialize)] +pub struct FeatureFlagArchivedAudit { + pub context: AuditContext, + pub project_id: i32, + pub flag_id: i32, + pub key: String, +} + +/// The one that matters operationally: this is the record of who turned a +/// feature on or off in production, and what it was set to before. +#[derive(Debug, Clone, Serialize)] +pub struct FeatureFlagEnvironmentValueSetAudit { + pub context: AuditContext, + pub project_id: i32, + pub flag_id: i32, + pub key: String, + pub environment_id: i32, + pub old_enabled: Option, + pub new_enabled: bool, + pub old_value: Option, + pub new_value: Option, +} + +impl_audit_operation!(FeatureFlagCreatedAudit, "FEATURE_FLAG_CREATED"); +impl_audit_operation!(FeatureFlagUpdatedAudit, "FEATURE_FLAG_UPDATED"); +impl_audit_operation!(FeatureFlagArchivedAudit, "FEATURE_FLAG_ARCHIVED"); +impl_audit_operation!( + FeatureFlagEnvironmentValueSetAudit, + "FEATURE_FLAG_ENVIRONMENT_VALUE_SET" +); diff --git a/crates/temps-flags/src/handlers/handler.rs b/crates/temps-flags/src/handlers/handler.rs new file mode 100644 index 000000000..98e756a77 --- /dev/null +++ b/crates/temps-flags/src/handlers/handler.rs @@ -0,0 +1,1016 @@ +//! HTTP handlers for feature flags. + +use std::sync::Arc; + +use axum::{ + extract::{Extension, Path, Query, State}, + http::{header, HeaderMap, HeaderValue, StatusCode}, + response::IntoResponse, + routing::{delete, get, patch, post, put}, + Json, Router, +}; +use serde::Deserialize; +use sha2::{Digest, Sha256}; +use temps_auth::{permission_guard, project_access_guard, project_scope_guard, RequireAuth}; +use temps_core::problemdetails::{self, Problem}; +use temps_core::RequestMetadata; +use tracing::error; +use utoipa::{IntoParams, OpenApi}; + +use super::audit::{ + AuditContext, FeatureFlagArchivedAudit, FeatureFlagCreatedAudit, + FeatureFlagEnvironmentValueSetAudit, FeatureFlagUpdatedAudit, +}; +use super::types::*; +use crate::error::FlagError; +use crate::eval::{FlagSnapshot, FlagValueType}; +use crate::services::{normalize_pagination, CreateFlag, SetEnvironmentValue, UpdateFlag}; + +#[derive(OpenApi)] +#[openapi( + paths( + list_flags, + create_flag, + get_flag, + update_flag, + archive_flag, + set_flag_environment, + get_flag_snapshot, + ), + components(schemas( + CreateFlagRequest, + UpdateFlagRequest, + SetFlagEnvironmentRequest, + FlagResponse, + FlagEnvironmentResponse, + FlagListResponse, + FlagSnapshotResponse, + ArchiveFlagResponse, + FlagSnapshot, + FlagValueType, + )), + tags(( + name = "Feature Flags", + description = "Runtime configuration that changes without a redeploy" + )) +)] +pub struct FlagsApiDoc; + +pub fn configure_routes() -> Router> { + Router::new() + .route("/projects/{project_id}/flags", get(list_flags)) + .route("/projects/{project_id}/flags", post(create_flag)) + .route("/projects/{project_id}/flags/{key}", get(get_flag)) + .route("/projects/{project_id}/flags/{key}", patch(update_flag)) + .route("/projects/{project_id}/flags/{key}", delete(archive_flag)) + .route( + "/projects/{project_id}/flags/{key}/environments/{environment_id}", + put(set_flag_environment), + ) + // Delivery endpoint for running services. Scope comes from the + // deployment token, not the URL. + .route("/flags/snapshot", get(get_flag_snapshot)) +} + +// ============================================================================= +// Error mapping +// ============================================================================= + +impl From for Problem { + fn from(error: FlagError) -> Self { + match error { + FlagError::NotFound { .. } => problemdetails::new(StatusCode::NOT_FOUND) + .with_title("Feature Flag Not Found") + .with_detail(error.to_string()), + + FlagError::EnvironmentNotFound { .. } => problemdetails::new(StatusCode::NOT_FOUND) + .with_title("Environment Not Found") + .with_detail(error.to_string()), + + FlagError::DuplicateKey { .. } => problemdetails::new(StatusCode::CONFLICT) + .with_title("Feature Flag Already Exists") + .with_detail(error.to_string()), + + // Cross-tenant attachment is a client error, not a server one, but + // it is worth distinguishing from a plain validation failure. + FlagError::EnvironmentNotInProject { .. } => { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Environment Not In Project") + .with_detail(error.to_string()) + } + + FlagError::InvalidKey { .. } => problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid Flag Key") + .with_detail(error.to_string()), + + FlagError::ValueTypeMismatch { .. } => problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Value Type Mismatch") + .with_detail(error.to_string()), + + FlagError::Validation { .. } => problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Validation Error") + .with_detail(error.to_string()), + + FlagError::TokenNotEnvironmentScoped { .. } => { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Environment Required") + .with_detail(error.to_string()) + } + + // A stored value_type that no longer parses is data corruption, not + // bad input. + FlagError::InvalidValueType { .. } => { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Invalid Stored Value Type") + .with_detail(error.to_string()) + } + + FlagError::Database(_) => problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Internal Server Error") + .with_detail(error.to_string()), + + FlagError::Serialization { .. } => { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Internal Server Error") + .with_detail(error.to_string()) + } + } + } +} + +// ============================================================================= +// Query parameters +// ============================================================================= + +#[derive(Debug, Deserialize, IntoParams)] +pub struct ListFlagsQuery { + /// Include archived flags. Defaults to false. + #[serde(default)] + pub include_archived: bool, + /// 1-indexed page number. Defaults to 1. + pub page: Option, + /// Items per page. Defaults to 20, capped at 100. + pub page_size: Option, +} + +#[derive(Debug, Deserialize, IntoParams)] +pub struct SnapshotQuery { + /// Required only when the calling token is project-wide rather than scoped + /// to a single environment. + pub environment_id: Option, +} + +// ============================================================================= +// Helpers +// ============================================================================= + +fn audit_context(auth: &temps_auth::AuthContext, metadata: &RequestMetadata) -> AuditContext { + AuditContext { + user_id: auth.user_id(), + ip_address: Some(metadata.ip_address.clone()), + user_agent: metadata.user_agent.clone(), + } +} + +/// Weak-ish entity tag over the serialized snapshot. +/// +/// The snapshot is sorted by key in the service, so equal flag state always +/// produces an equal tag and the SDK's poll collapses to a 304. +fn snapshot_etag(flags: &[FlagSnapshot]) -> Result { + let body = serde_json::to_vec(flags).map_err(|e| FlagError::Serialization { + key: "".to_string(), + reason: e.to_string(), + })?; + + let mut hasher = Sha256::new(); + hasher.update(&body); + let digest = hasher.finalize(); + + Ok(format!("\"{}\"", hex::encode(&digest[..16]))) +} + +// ============================================================================= +// Management handlers +// ============================================================================= + +#[utoipa::path( + tag = "Feature Flags", + get, + path = "/projects/{project_id}/flags", + params(("project_id" = i32, Path, description = "Project ID"), ListFlagsQuery), + responses( + (status = 200, description = "Flags listed", body = FlagListResponse), + (status = 401, description = "Unauthorized"), + (status = 403, description = "Insufficient permissions"), + (status = 500, description = "Internal server error") + ), + security(("bearer_auth" = [])) +)] +pub async fn list_flags( + RequireAuth(auth): RequireAuth, + State(state): State>, + Path(project_id): Path, + Query(query): Query, +) -> Result { + permission_guard!(auth, FlagsRead); + project_scope_guard!(auth, project_id); + project_access_guard!(auth, project_id, &state.project_access_checker); + + let (entries, total) = state + .flag_service + .list( + project_id, + query.include_archived, + query.page, + query.page_size, + ) + .await?; + + let flags: Vec = entries + .into_iter() + .map(|entry| FlagResponse::new(entry.flag, entry.environments)) + .collect(); + + // Same clamp the query used, so `total_pages` can never describe a page + // size the server did not actually serve. + let (page, page_size) = normalize_pagination(query.page, query.page_size); + let total_pages = total.div_ceil(page_size); + + Ok(Json(FlagListResponse { + flags, + total, + page, + page_size, + total_pages, + })) +} + +#[utoipa::path( + tag = "Feature Flags", + post, + path = "/projects/{project_id}/flags", + params(("project_id" = i32, Path, description = "Project ID")), + request_body = CreateFlagRequest, + responses( + (status = 201, description = "Flag created", body = FlagResponse), + (status = 400, description = "Validation error"), + (status = 401, description = "Unauthorized"), + (status = 403, description = "Insufficient permissions"), + (status = 409, description = "Flag key already exists"), + (status = 500, description = "Internal server error") + ), + security(("bearer_auth" = [])) +)] +pub async fn create_flag( + RequireAuth(auth): RequireAuth, + State(state): State>, + Extension(metadata): Extension, + Path(project_id): Path, + Json(request): Json, +) -> Result { + permission_guard!(auth, FlagsWrite); + project_scope_guard!(auth, project_id); + project_access_guard!(auth, project_id, &state.project_access_checker); + + let flag = state + .flag_service + .create( + project_id, + CreateFlag { + key: request.key, + value_type: request.value_type, + default_value: request.default_value, + description: request.description, + client_visible: request.client_visible, + }, + ) + .await?; + + let audit = FeatureFlagCreatedAudit { + context: audit_context(&auth, &metadata), + project_id, + flag_id: flag.id, + key: flag.key.clone(), + value_type: flag.value_type.clone(), + default_value: flag.default_value.clone(), + client_visible: flag.client_visible, + }; + if let Err(e) = state.audit_service.create_audit_log(&audit).await { + error!( + "Failed to create audit log for feature flag creation: {}", + e + ); + } + + Ok(( + StatusCode::CREATED, + Json(FlagResponse::new(flag, Vec::new())), + )) +} + +#[utoipa::path( + tag = "Feature Flags", + get, + path = "/projects/{project_id}/flags/{key}", + params( + ("project_id" = i32, Path, description = "Project ID"), + ("key" = String, Path, description = "Flag key") + ), + responses( + (status = 200, description = "Flag retrieved", body = FlagResponse), + (status = 401, description = "Unauthorized"), + (status = 403, description = "Insufficient permissions"), + (status = 404, description = "Flag not found"), + (status = 500, description = "Internal server error") + ), + security(("bearer_auth" = [])) +)] +pub async fn get_flag( + RequireAuth(auth): RequireAuth, + State(state): State>, + Path((project_id, key)): Path<(i32, String)>, +) -> Result { + permission_guard!(auth, FlagsRead); + project_scope_guard!(auth, project_id); + project_access_guard!(auth, project_id, &state.project_access_checker); + + let entry = state.flag_service.get(project_id, &key).await?; + + Ok(Json(FlagResponse::new(entry.flag, entry.environments))) +} + +#[utoipa::path( + tag = "Feature Flags", + patch, + path = "/projects/{project_id}/flags/{key}", + params( + ("project_id" = i32, Path, description = "Project ID"), + ("key" = String, Path, description = "Flag key") + ), + request_body = UpdateFlagRequest, + responses( + (status = 200, description = "Flag updated", body = FlagResponse), + (status = 400, description = "Validation error"), + (status = 401, description = "Unauthorized"), + (status = 403, description = "Insufficient permissions"), + (status = 404, description = "Flag not found"), + (status = 500, description = "Internal server error") + ), + security(("bearer_auth" = [])) +)] +pub async fn update_flag( + RequireAuth(auth): RequireAuth, + State(state): State>, + Extension(metadata): Extension, + Path((project_id, key)): Path<(i32, String)>, + Json(request): Json, +) -> Result { + permission_guard!(auth, FlagsWrite); + project_scope_guard!(auth, project_id); + project_access_guard!(auth, project_id, &state.project_access_checker); + + let before = state.flag_service.get(project_id, &key).await?.flag; + + let flag = state + .flag_service + .update( + project_id, + &key, + UpdateFlag { + default_value: request.default_value, + description: request.description, + client_visible: request.client_visible, + }, + ) + .await?; + + let audit = FeatureFlagUpdatedAudit { + context: audit_context(&auth, &metadata), + project_id, + flag_id: flag.id, + key: flag.key.clone(), + old_default_value: before.default_value, + new_default_value: flag.default_value.clone(), + old_client_visible: before.client_visible, + new_client_visible: flag.client_visible, + }; + if let Err(e) = state.audit_service.create_audit_log(&audit).await { + error!("Failed to create audit log for feature flag update: {}", e); + } + + let environments = state.flag_service.get(project_id, &key).await?.environments; + + Ok(Json(FlagResponse::new(flag, environments))) +} + +#[utoipa::path( + tag = "Feature Flags", + delete, + path = "/projects/{project_id}/flags/{key}", + params( + ("project_id" = i32, Path, description = "Project ID"), + ("key" = String, Path, description = "Flag key") + ), + responses( + (status = 200, description = "Flag archived", body = ArchiveFlagResponse), + (status = 401, description = "Unauthorized"), + (status = 403, description = "Insufficient permissions"), + (status = 404, description = "Flag not found"), + (status = 500, description = "Internal server error") + ), + security(("bearer_auth" = [])) +)] +pub async fn archive_flag( + RequireAuth(auth): RequireAuth, + State(state): State>, + Extension(metadata): Extension, + Path((project_id, key)): Path<(i32, String)>, +) -> Result { + permission_guard!(auth, FlagsDelete); + project_scope_guard!(auth, project_id); + project_access_guard!(auth, project_id, &state.project_access_checker); + + let flag = state.flag_service.archive(project_id, &key).await?; + + let audit = FeatureFlagArchivedAudit { + context: audit_context(&auth, &metadata), + project_id, + flag_id: flag.id, + key: flag.key.clone(), + }; + if let Err(e) = state.audit_service.create_audit_log(&audit).await { + error!("Failed to create audit log for feature flag archive: {}", e); + } + + Ok(Json(ArchiveFlagResponse { + key: flag.key, + archived_at: flag.archived_at.map(|t| t.to_rfc3339()), + })) +} + +/// Set a flag's value in one environment, and/or flip its kill switch. +#[utoipa::path( + tag = "Feature Flags", + put, + path = "/projects/{project_id}/flags/{key}/environments/{environment_id}", + params( + ("project_id" = i32, Path, description = "Project ID"), + ("key" = String, Path, description = "Flag key"), + ("environment_id" = i32, Path, description = "Environment ID") + ), + request_body = SetFlagEnvironmentRequest, + responses( + (status = 200, description = "Environment value set", body = FlagEnvironmentResponse), + (status = 400, description = "Validation error"), + (status = 401, description = "Unauthorized"), + (status = 403, description = "Insufficient permissions"), + (status = 404, description = "Flag or environment not found"), + (status = 500, description = "Internal server error") + ), + security(("bearer_auth" = [])) +)] +pub async fn set_flag_environment( + RequireAuth(auth): RequireAuth, + State(state): State>, + Extension(metadata): Extension, + Path((project_id, key, environment_id)): Path<(i32, String, i32)>, + Json(request): Json, +) -> Result { + permission_guard!(auth, FlagsWrite); + project_scope_guard!(auth, project_id); + project_access_guard!(auth, project_id, &state.project_access_checker); + + // Captured before the write so the audit entry records what the flag was + // actually changed *from* — the only record that a production behaviour + // change happened, since a flag flip leaves no deployment behind. + let before = state + .flag_service + .get(project_id, &key) + .await? + .environments + .into_iter() + .find(|row| row.environment_id == environment_id); + + let model = state + .flag_service + .set_environment_value( + project_id, + &key, + environment_id, + SetEnvironmentValue { + value: request.value, + enabled: request.enabled, + }, + ) + .await?; + + let audit = FeatureFlagEnvironmentValueSetAudit { + context: audit_context(&auth, &metadata), + project_id, + flag_id: model.flag_id, + key: key.clone(), + environment_id, + old_enabled: before.as_ref().map(|row| row.enabled), + new_enabled: model.enabled, + old_value: before.and_then(|row| row.value), + new_value: model.value.clone(), + }; + if let Err(e) = state.audit_service.create_audit_log(&audit).await { + error!( + "Failed to create audit log for feature flag environment value: {}", + e + ); + } + + Ok(Json(FlagEnvironmentResponse::from(model))) +} + +// ============================================================================= +// Delivery handler +// ============================================================================= + +/// Every flag for the caller's environment, collapsed to what the evaluator +/// needs. +/// +/// Scope comes from the deployment token, never from the URL: a container's +/// baked-in `TEMPS_API_TOKEN` identifies exactly one project (and usually one +/// environment), so a compromised app cannot read another tenant's flags by +/// changing a path parameter. +/// +/// Supports `If-None-Match`, so the SDK's background poll is a 304 in the +/// common case. +#[utoipa::path( + tag = "Feature Flags", + get, + path = "/flags/snapshot", + params(SnapshotQuery), + responses( + (status = 200, description = "Snapshot for the environment", body = FlagSnapshotResponse), + (status = 304, description = "Snapshot unchanged"), + (status = 400, description = "Environment could not be determined"), + (status = 401, description = "Unauthorized"), + (status = 403, description = "Insufficient permissions"), + (status = 500, description = "Internal server error") + ), + security(("bearer_auth" = [])) +)] +pub async fn get_flag_snapshot( + RequireAuth(auth): RequireAuth, + State(state): State>, + headers: HeaderMap, + Query(query): Query, +) -> Result { + permission_guard!(auth, FlagsRead); + + let token_info = auth.deployment_token_info(); + + // A deployment token pins the project. Anything else (session, API key) + // must name the project it wants and pass the access guard. + let project_id = match auth.project_id() { + Some(project_id) => project_id, + None => { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Deployment Token Required") + .with_detail( + "The flag snapshot endpoint is scoped by a deployment token. \ + Use TEMPS_API_TOKEN, or read flags via /projects/{project_id}/flags.", + )) + } + }; + + // Prefer the token's own environment. A project-wide token has to say + // which environment it means, and the service verifies that environment + // actually belongs to this project before returning anything. + let environment_id = token_info + .and_then(|info| info.environment_id) + .or(query.environment_id) + .ok_or_else(|| Problem::from(FlagError::TokenNotEnvironmentScoped { project_id }))?; + + let flags = state + .flag_service + // Server-side callers see every flag, including server-only ones. The + // client_visible filter belongs to the unauthenticated same-origin + // endpoint, which does not exist yet. + .snapshot(project_id, environment_id, false) + .await + // Collapse "no such environment" and "someone else's environment" into + // one response. Distinguishing them lets a token holder probe + // sequential ids to learn which environments exist platform-wide, and a + // calling app has no reason to tell the two apart. + .map_err(|error| match error { + FlagError::EnvironmentNotFound { .. } | FlagError::EnvironmentNotInProject { .. } => { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Environment Not Available") + .with_detail( + "The requested environment does not exist in this token's project.", + ) + } + other => Problem::from(other), + })?; + + let etag = snapshot_etag(&flags)?; + + if let Some(requested) = headers.get(header::IF_NONE_MATCH) { + if requested.as_bytes() == etag.as_bytes() { + return Ok(StatusCode::NOT_MODIFIED.into_response()); + } + } + + let mut response_headers = HeaderMap::new(); + match HeaderValue::from_str(&etag) { + Ok(value) => { + response_headers.insert(header::ETAG, value); + } + Err(e) => { + // A non-ASCII ETag is impossible (hex), but degrade rather than + // fail the caller's flag fetch. + error!("Failed to build ETag header for flag snapshot: {}", e); + } + } + + Ok(( + StatusCode::OK, + response_headers, + Json(FlagSnapshotResponse { + environment_id, + flags, + }), + ) + .into_response()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::services::FlagService; + use sea_orm::{DatabaseBackend, MockDatabase}; + use temps_auth::context::AuthContext; + use temps_auth::permissions::{Permission, Role}; + use temps_entities::deployment_tokens::DeploymentTokenPermission; + use temps_entities::users; + + // ===================================================================== + // Handler guards + // ===================================================================== + + /// Minimal `AuditLogger` so handler tests don't need the audit crate's + /// database and geo-IP dependencies. + struct NoopAuditLogger; + + #[async_trait::async_trait] + impl temps_core::AuditLogger for NoopAuditLogger { + async fn create_audit_log( + &self, + _operation: &dyn temps_core::AuditOperation, + ) -> anyhow::Result<()> { + Ok(()) + } + } + + fn test_user() -> users::Model { + let now = chrono::Utc::now(); + users::Model { + id: 1, + name: "Test User".to_string(), + email: "test@example.com".to_string(), + password_hash: None, + email_verified: true, + email_verification_token: None, + email_verification_expires: None, + password_reset_token: None, + password_reset_expires: None, + deleted_at: None, + mfa_secret: None, + mfa_enabled: false, + mfa_recovery_codes: None, + oidc_subject: None, + oidc_provider_id: None, + created_at: now, + updated_at: now, + } + } + + fn test_metadata() -> RequestMetadata { + RequestMetadata { + ip_address: "127.0.0.1".to_string(), + user_agent: "test".to_string(), + headers: HeaderMap::new(), + visitor_id_cookie: None, + session_id_cookie: None, + base_url: "http://localhost".to_string(), + scheme: "http".to_string(), + host: "localhost".to_string(), + is_secure: false, + } + } + + fn app_state() -> Arc { + let db = Arc::new(MockDatabase::new(DatabaseBackend::Postgres).into_connection()); + Arc::new(FlagsAppState { + flag_service: Arc::new(FlagService::new(db)), + audit_service: Arc::new(NoopAuditLogger), + project_access_checker: None, + }) + } + + fn list_query() -> ListFlagsQuery { + ListFlagsQuery { + include_archived: false, + page: None, + page_size: None, + } + } + + /// The Problem status if the handler rejected the request, or `None` if it + /// passed the guards and went on to the service. + async fn list_rejection(auth: AuthContext) -> Option { + list_flags( + RequireAuth(auth), + State(app_state()), + Path(1), + Query(list_query()), + ) + .await + .err() + .map(|p| p.status_code) + } + + async fn archive_rejection(auth: AuthContext) -> Option { + archive_flag( + RequireAuth(auth), + State(app_state()), + Extension(test_metadata()), + Path((1, "checkout.v2".to_string())), + ) + .await + .err() + .map(|p| p.status_code) + } + + #[tokio::test] + async fn reader_cannot_archive_a_flag() { + assert_eq!( + archive_rejection(AuthContext::new_session(test_user(), Role::Reader)).await, + Some(StatusCode::FORBIDDEN), + "flags:delete must not be implied by a read-only role" + ); + } + + #[tokio::test] + async fn reader_can_reach_the_list_handler() { + assert_ne!( + list_rejection(AuthContext::new_session(test_user(), Role::Reader)).await, + Some(StatusCode::FORBIDDEN), + "Reader holds flags:read and must pass the guard" + ); + } + + #[tokio::test] + async fn api_key_scoped_to_read_cannot_write() { + let read_only = || { + AuthContext::new_api_key( + test_user(), + None, + Some(vec![Permission::FlagsRead]), + "flags-read-key".to_string(), + 1, + ) + }; + + assert_ne!( + list_rejection(read_only()).await, + Some(StatusCode::FORBIDDEN), + "a flags:read key must be able to list" + ); + assert_eq!( + archive_rejection(read_only()).await, + Some(StatusCode::FORBIDDEN), + "a flags:read key must NOT be able to archive" + ); + } + + /// Regression: a deployment token scoped to project 1 must not be able to + /// read project 2's flags by putting a different id in the path. + /// + /// `project_access_guard!` deliberately skips deployment tokens (they carry + /// no user identity for a team-membership check), so `project_scope_guard!` + /// is the *only* thing confining them. Without it this returned 200 and the + /// other tenant's flag values. + #[tokio::test] + async fn deployment_token_cannot_read_another_projects_flags() { + let foreign_project = AuthContext::new_deployment_token( + 1, + Some(1), + None, + 1, + "app".to_string(), + vec![DeploymentTokenPermission::FlagsRead], + ); + + let rejection = list_flags( + RequireAuth(foreign_project), + State(app_state()), + Path(2), + Query(list_query()), + ) + .await + .err() + .map(|p| p.status_code); + + assert_eq!( + rejection, + Some(StatusCode::FORBIDDEN), + "a project-1 token must not list project 2's flags" + ); + } + + /// Same confinement for the single-flag read. + #[tokio::test] + async fn deployment_token_cannot_get_another_projects_flag() { + let rejection = get_flag( + RequireAuth(AuthContext::new_deployment_token( + 1, + Some(1), + None, + 1, + "app".to_string(), + vec![DeploymentTokenPermission::FlagsRead], + )), + State(app_state()), + Path((2, "victim.secret".to_string())), + ) + .await + .err() + .map(|p| p.status_code); + + assert_eq!(rejection, Some(StatusCode::FORBIDDEN)); + } + + /// A full-access deployment token is still a *project-scoped* credential: + /// the wildcard grants flag reads, not other tenants' data. + #[tokio::test] + async fn full_access_deployment_token_is_still_project_confined() { + let rejection = list_flags( + RequireAuth(AuthContext::new_deployment_token( + 1, + Some(1), + None, + 1, + "app".to_string(), + vec![DeploymentTokenPermission::FullAccess], + )), + State(app_state()), + Path(2), + Query(list_query()), + ) + .await + .err() + .map(|p| p.status_code); + + assert_eq!(rejection, Some(StatusCode::FORBIDDEN)); + } + + /// The token's own project must still work, or the guard is too strict. + #[tokio::test] + async fn deployment_token_can_read_its_own_project() { + let rejection = list_flags( + RequireAuth(AuthContext::new_deployment_token( + 1, + Some(1), + None, + 1, + "app".to_string(), + vec![DeploymentTokenPermission::FlagsRead], + )), + State(app_state()), + Path(1), + Query(list_query()), + ) + .await + .err() + .map(|p| p.status_code); + + assert_ne!(rejection, Some(StatusCode::FORBIDDEN)); + } + + /// A container's baked-in `TEMPS_API_TOKEN` must never be able to change a + /// production flag, only read one. + #[tokio::test] + async fn deployment_token_is_read_only() { + let token = || { + AuthContext::new_deployment_token( + 1, + Some(1), + None, + 1, + "app".to_string(), + vec![DeploymentTokenPermission::FlagsRead], + ) + }; + + assert_eq!( + archive_rejection(token()).await, + Some(StatusCode::FORBIDDEN), + "a deployment token must not archive flags" + ); + } + + /// The snapshot endpoint takes its scope from the token, never the URL. + /// A session principal has no project, so it must be turned away rather + /// than defaulting to something. + #[tokio::test] + async fn snapshot_requires_a_deployment_token() { + let result = get_flag_snapshot( + RequireAuth(AuthContext::new_session(test_user(), Role::Admin)), + State(app_state()), + HeaderMap::new(), + Query(SnapshotQuery { + environment_id: Some(1), + }), + ) + .await; + + assert_eq!( + result.err().map(|p| p.status_code), + Some(StatusCode::BAD_REQUEST) + ); + } + + /// A project-wide token names no environment, so one must be supplied — + /// and the service still checks it belongs to the token's project. + #[tokio::test] + async fn snapshot_requires_an_environment_for_a_project_wide_token() { + let result = get_flag_snapshot( + RequireAuth(AuthContext::new_deployment_token( + 1, + None, + None, + 1, + "app".to_string(), + vec![DeploymentTokenPermission::FlagsRead], + )), + State(app_state()), + HeaderMap::new(), + Query(SnapshotQuery { + environment_id: None, + }), + ) + .await; + + assert_eq!( + result.err().map(|p| p.status_code), + Some(StatusCode::BAD_REQUEST) + ); + } + + // ===================================================================== + // ETag + // ===================================================================== + + fn snapshot(key: &str, value: serde_json::Value) -> FlagSnapshot { + FlagSnapshot { + key: key.to_string(), + value_type: FlagValueType::Bool, + default_value: serde_json::json!(false), + enabled: true, + environment_value: Some(value), + } + } + + #[test] + fn etag_is_stable_for_identical_snapshots() { + let a = vec![snapshot("checkout.v2", serde_json::json!(true))]; + let b = vec![snapshot("checkout.v2", serde_json::json!(true))]; + + assert_eq!(snapshot_etag(&a).unwrap(), snapshot_etag(&b).unwrap()); + } + + #[test] + fn etag_changes_when_a_value_changes() { + let a = vec![snapshot("checkout.v2", serde_json::json!(true))]; + let b = vec![snapshot("checkout.v2", serde_json::json!(false))]; + + assert_ne!(snapshot_etag(&a).unwrap(), snapshot_etag(&b).unwrap()); + } + + #[test] + fn etag_changes_when_a_flag_is_added() { + let a = vec![snapshot("checkout.v2", serde_json::json!(true))]; + let b = vec![ + snapshot("checkout.v2", serde_json::json!(true)), + snapshot("new.search", serde_json::json!(true)), + ]; + + assert_ne!(snapshot_etag(&a).unwrap(), snapshot_etag(&b).unwrap()); + } + + #[test] + fn etag_is_quoted_and_hex() { + let etag = snapshot_etag(&[snapshot("a", serde_json::json!(true))]).unwrap(); + + assert!(etag.starts_with('"') && etag.ends_with('"'), "{etag}"); + let inner = etag.trim_matches('"'); + assert_eq!(inner.len(), 32); + assert!(inner.chars().all(|c| c.is_ascii_hexdigit()), "{etag}"); + } +} diff --git a/crates/temps-flags/src/handlers/mod.rs b/crates/temps-flags/src/handlers/mod.rs new file mode 100644 index 000000000..82eeb4d0d --- /dev/null +++ b/crates/temps-flags/src/handlers/mod.rs @@ -0,0 +1,6 @@ +pub mod audit; +pub mod handler; +pub mod types; + +pub use handler::{configure_routes, FlagsApiDoc}; +pub use types::FlagsAppState; diff --git a/crates/temps-flags/src/handlers/types.rs b/crates/temps-flags/src/handlers/types.rs new file mode 100644 index 000000000..d73b9dede --- /dev/null +++ b/crates/temps-flags/src/handlers/types.rs @@ -0,0 +1,201 @@ +//! Request/response DTOs and shared handler state for feature flags. + +use std::sync::Arc; + +use serde::{Deserialize, Serialize}; +use temps_core::{AuditLogger, ProjectAccessChecker}; +use temps_entities::{feature_flag_environments, feature_flags}; +use utoipa::ToSchema; + +use crate::eval::{FlagSnapshot, FlagValueType}; +use crate::services::FlagService; + +pub struct FlagsAppState { + pub flag_service: Arc, + pub audit_service: Arc, + /// Team-based project access checker (registered by a plugin; `None` in + /// plain OSS, where the guard is a no-op). Confines callers to projects + /// they may reach. + pub project_access_checker: Option>, +} + +// ============================================================================= +// Tri-state deserializers +// ============================================================================= +// +// Serde's plain `Option>` collapses a present JSON `null` into `None`, +// which makes "clear this field" indistinguishable from "leave it alone". These +// mirror the helpers in `temps-environments`. + +/// - field absent → `None` (leave unchanged) +/// - field present as `null` → `Some(None)` (clear the description) +/// - field present as a string → `Some(Some(s))` +fn deserialize_optional_optional_string<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: serde::Deserializer<'de>, +{ + let value: serde_json::Value = serde::Deserialize::deserialize(deserializer)?; + match value { + serde_json::Value::Null => Ok(Some(None)), + v => { + let s: String = serde_json::from_value(v).map_err(serde::de::Error::custom)?; + Ok(Some(Some(s))) + } + } +} + +/// - field absent → `None` (leave unchanged) +/// - field present as `null` → `Some(None)` (clear the override, inherit default) +/// - anything else → `Some(Some(value))` +/// +/// `null` is unambiguous here because it is never a legal flag value: a flag +/// must always resolve to something usable, so `null` can only mean "unset". +fn deserialize_optional_optional_value<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: serde::Deserializer<'de>, +{ + let value: serde_json::Value = serde::Deserialize::deserialize(deserializer)?; + match value { + serde_json::Value::Null => Ok(Some(None)), + v => Ok(Some(Some(v))), + } +} + +// ============================================================================= +// Requests +// ============================================================================= + +#[derive(Debug, Clone, Deserialize, ToSchema)] +pub struct CreateFlagRequest { + /// Stable key used in application code. Immutable after create. + #[schema(example = "checkout.v2")] + pub key: String, + /// Fixed at create: retyping would invalidate every stored value and every + /// call site. + pub value_type: FlagValueType, + /// Served whenever evaluation cannot do better. Must match `value_type`. + /// + /// Left unannotated so utoipa emits a free-form schema: a bool flag's + /// default is `false`, not an object, and `value_type = Object` would tell + /// every generated client otherwise. + #[schema(example = false)] + pub default_value: serde_json::Value, + #[serde(default)] + pub description: Option, + /// Whether the flag may be exposed on the unauthenticated same-origin + /// evaluation endpoint. Defaults to `false`: flags are server-only unless + /// explicitly opted in, because targeting rules can encode business logic. + #[serde(default)] + pub client_visible: bool, +} + +#[derive(Debug, Clone, Deserialize, ToSchema)] +pub struct UpdateFlagRequest { + /// Must match the flag's existing `value_type`. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub default_value: Option, + /// Tri-state: absent leaves it, `null` clears it, a string sets it. + #[serde(default, deserialize_with = "deserialize_optional_optional_string")] + pub description: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub client_visible: Option, +} + +#[derive(Debug, Clone, Deserialize, ToSchema)] +pub struct SetFlagEnvironmentRequest { + /// Tri-state: absent leaves the override, `null` clears it (inherit the + /// flag default), anything else sets it. Must match `value_type`. + #[serde(default, deserialize_with = "deserialize_optional_optional_value")] + pub value: Option>, + /// The kill switch. `false` makes the flag serve its default regardless of + /// any override — and, once targeting exists, regardless of any rule. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub enabled: Option, +} + +// ============================================================================= +// Responses +// ============================================================================= + +#[derive(Debug, Clone, Serialize, ToSchema)] +pub struct FlagEnvironmentResponse { + pub environment_id: i32, + pub enabled: bool, + pub value: Option, +} + +impl From for FlagEnvironmentResponse { + fn from(model: feature_flag_environments::Model) -> Self { + Self { + environment_id: model.environment_id, + enabled: model.enabled, + value: model.value, + } + } +} + +#[derive(Debug, Clone, Serialize, ToSchema)] +pub struct FlagResponse { + pub id: i32, + pub key: String, + pub value_type: String, + pub default_value: serde_json::Value, + pub description: Option, + pub client_visible: bool, + pub archived_at: Option, + pub created_at: String, + pub updated_at: String, + /// Per-environment overrides. Empty means the flag inherits its default + /// everywhere. + pub environments: Vec, +} + +impl FlagResponse { + pub fn new( + flag: feature_flags::Model, + environments: Vec, + ) -> Self { + Self { + id: flag.id, + key: flag.key, + value_type: flag.value_type, + default_value: flag.default_value, + description: flag.description, + client_visible: flag.client_visible, + archived_at: flag.archived_at.map(|t| t.to_rfc3339()), + created_at: flag.created_at.to_rfc3339(), + updated_at: flag.updated_at.to_rfc3339(), + environments: environments.into_iter().map(Into::into).collect(), + } + } +} + +/// Note the absence of `salt`: it is never exposed. Publishing the bucketing +/// salt would let a client predict, and self-select into, a rollout cohort. +#[derive(Debug, Clone, Serialize, ToSchema)] +pub struct FlagListResponse { + pub flags: Vec, + /// Total flags matching the filter, across all pages. + pub total: u64, + pub page: u64, + pub page_size: u64, + pub total_pages: u64, +} + +#[derive(Debug, Clone, Serialize, ToSchema)] +pub struct FlagSnapshotResponse { + pub environment_id: i32, + /// Flags collapsed to what the evaluator needs, sorted by key so the + /// serialized form — and therefore the ETag — is stable. + pub flags: Vec, +} + +#[derive(Debug, Clone, Serialize, ToSchema)] +pub struct ArchiveFlagResponse { + pub key: String, + pub archived_at: Option, +} diff --git a/crates/temps-flags/src/lib.rs b/crates/temps-flags/src/lib.rs new file mode 100644 index 000000000..2f138fe85 --- /dev/null +++ b/crates/temps-flags/src/lib.rs @@ -0,0 +1,27 @@ +//! temps-flags: feature flags for the Temps platform (ADR-034, Phase 1). +//! +//! A flag is defined once per project and its value is overridden per +//! environment. Changing a value takes effect in seconds; changing an +//! environment variable requires a redeploy. That difference is the entire +//! reason this crate exists. +//! +//! Phase 1 deliberately ships only the kill switch — set a value per +//! environment, flip it without a redeploy. What it also does is fix the parts +//! that are expensive to change once callers depend on them: the resolution +//! order, the `reason` wire contract, typed values, the `client_visible` +//! security default, and the bucketing algorithm. Targeting rules slot into a +//! reserved step in [`eval::evaluate`] without disturbing any of it. + +pub mod error; +pub mod eval; +pub mod handlers; +pub mod plugin; +pub mod services; + +pub use error::FlagError; +pub use eval::{ + bucket, evaluate, not_found, AttributeValue, EvalContext, EvalReason, Evaluation, FlagSnapshot, + FlagValueType, +}; +pub use plugin::FlagsPlugin; +pub use services::FlagService; diff --git a/crates/temps-flags/src/plugin.rs b/crates/temps-flags/src/plugin.rs new file mode 100644 index 000000000..0b302c3bc --- /dev/null +++ b/crates/temps-flags/src/plugin.rs @@ -0,0 +1,74 @@ +//! Feature-flag plugin registration. +//! +//! No containers, no background tasks, no external service: flags are rows in +//! the control-plane database, so this plugin registers a service and some +//! routes and is done. + +use std::future::Future; +use std::pin::Pin; +use std::sync::Arc; + +use sea_orm::DatabaseConnection; +use temps_core::plugin::{ + PluginContext, PluginError, PluginRoutes, ServiceRegistrationContext, TempsPlugin, +}; +use temps_core::AuditLogger; +use tracing::debug; +use utoipa::openapi::OpenApi; +use utoipa::OpenApi as OpenApiTrait; + +use crate::handlers::{configure_routes, FlagsApiDoc, FlagsAppState}; +use crate::services::FlagService; + +pub struct FlagsPlugin; + +impl FlagsPlugin { + pub fn new() -> Self { + Self + } +} + +impl Default for FlagsPlugin { + fn default() -> Self { + Self::new() + } +} + +impl TempsPlugin for FlagsPlugin { + fn name(&self) -> &'static str { + "flags" + } + + fn register_services<'a>( + &'a self, + context: &'a ServiceRegistrationContext, + ) -> Pin> + Send + 'a>> { + Box::pin(async move { + let db = context.require_service::(); + context.register_service(Arc::new(FlagService::new(db))); + + debug!("Feature flag plugin services registered successfully"); + Ok(()) + }) + } + + fn configure_routes(&self, context: &PluginContext) -> Option { + let flag_service = context.require_service::(); + let audit_service = context.require_service::(); + // Optional team-based access checker (present only when a plugin + // registers one); `None` in plain OSS, where the guard is a no-op. + let project_access_checker = context.get_service::(); + + let app_state = Arc::new(FlagsAppState { + flag_service, + audit_service, + project_access_checker, + }); + + Some(PluginRoutes::new(configure_routes().with_state(app_state))) + } + + fn openapi_schema(&self) -> Option { + Some(::openapi()) + } +} diff --git a/crates/temps-flags/src/services/flag_service.rs b/crates/temps-flags/src/services/flag_service.rs new file mode 100644 index 000000000..196c38e04 --- /dev/null +++ b/crates/temps-flags/src/services/flag_service.rs @@ -0,0 +1,955 @@ +//! Business logic for feature flags. + +use std::collections::HashMap; +use std::sync::Arc; + +use sea_orm::{ + ActiveModelTrait, ActiveValue::Set, ColumnTrait, DatabaseConnection, EntityTrait, + PaginatorTrait, QueryFilter, QueryOrder, TransactionTrait, +}; +use temps_entities::{environments, feature_flag_environments, feature_flags}; +use tracing::{debug, info}; + +use crate::error::FlagError; +use crate::eval::{FlagSnapshot, FlagValueType}; + +/// Pagination defaults, per the project-wide convention. +const DEFAULT_PAGE_SIZE: u64 = 20; +const MAX_PAGE_SIZE: u64 = 100; + +/// Maximum length of a flag key, matching the column width. +const MAX_KEY_LEN: usize = 128; +/// Maximum length of a flag description, matching the column width. +const MAX_DESCRIPTION_LEN: usize = 512; + +/// A flag definition together with its per-environment overrides. +#[derive(Debug, Clone)] +pub struct FlagWithEnvironments { + pub flag: feature_flags::Model, + pub environments: Vec, +} + +/// Fields accepted when creating a flag. +#[derive(Debug, Clone)] +pub struct CreateFlag { + pub key: String, + pub value_type: FlagValueType, + pub default_value: serde_json::Value, + pub description: Option, + pub client_visible: bool, +} + +/// Fields accepted when updating a flag definition. `None` means "leave alone". +/// +/// `key` and `value_type` are deliberately absent: keys leak into user source +/// code and analytics dimensions, and retyping would invalidate every stored +/// value. Both are immutable after create. +#[derive(Debug, Clone, Default)] +pub struct UpdateFlag { + pub default_value: Option, + pub description: Option>, + pub client_visible: Option, +} + +/// Fields accepted when setting a flag's value in one environment. +#[derive(Debug, Clone, Default)] +pub struct SetEnvironmentValue { + /// `Some(None)` clears the override so the flag inherits its default. + pub value: Option>, + pub enabled: Option, +} + +pub struct FlagService { + db: Arc, +} + +impl FlagService { + pub fn new(db: Arc) -> Self { + Self { db } + } + + // --------------------------------------------------------------------- + // Validation + // --------------------------------------------------------------------- + + /// Flag keys must match `[a-z0-9][a-z0-9._-]*`. + /// + /// Hand-rolled rather than pulling in a regex: the rule is small, and the + /// error message can name the offending character, which a regex failure + /// cannot. + fn validate_key(key: &str) -> Result<(), FlagError> { + if key.is_empty() { + return Err(FlagError::InvalidKey { + key: key.to_string(), + reason: "key is empty".to_string(), + }); + } + if key.len() > MAX_KEY_LEN { + return Err(FlagError::InvalidKey { + key: key.to_string(), + reason: format!("key is {} characters", key.len()), + }); + } + + let mut chars = key.chars(); + // Unwrap-free: emptiness was rejected above, but handle it anyway. + let Some(first) = chars.next() else { + return Err(FlagError::InvalidKey { + key: key.to_string(), + reason: "key is empty".to_string(), + }); + }; + if !first.is_ascii_lowercase() && !first.is_ascii_digit() { + return Err(FlagError::InvalidKey { + key: key.to_string(), + reason: format!("first character '{first}' must be a-z or 0-9"), + }); + } + + for c in chars { + let ok = c.is_ascii_lowercase() || c.is_ascii_digit() || matches!(c, '.' | '_' | '-'); + if !ok { + return Err(FlagError::InvalidKey { + key: key.to_string(), + reason: format!("character '{c}' is not allowed"), + }); + } + } + + Ok(()) + } + + fn validate_value( + key: &str, + value_type: FlagValueType, + value: &serde_json::Value, + field: &str, + ) -> Result<(), FlagError> { + if value_type.matches(value) { + return Ok(()); + } + Err(FlagError::ValueTypeMismatch { + key: key.to_string(), + value_type: value_type.as_str().to_string(), + value: value.to_string(), + field: field.to_string(), + }) + } + + fn validate_description(key: &str, description: &Option) -> Result<(), FlagError> { + if let Some(text) = description { + if text.len() > MAX_DESCRIPTION_LEN { + return Err(FlagError::Validation { + key: key.to_string(), + message: format!( + "description is {} characters, maximum is {MAX_DESCRIPTION_LEN}", + text.len() + ), + }); + } + } + Ok(()) + } + + /// Generate a per-flag bucketing salt. + /// + /// Nothing reads this in Phase 1. It exists so percentage bucketing is + /// stable from the first rollout — a salt introduced after subjects are + /// already assigned would reshuffle every live experiment. + fn generate_salt() -> String { + uuid::Uuid::new_v4().simple().to_string() + } + + // --------------------------------------------------------------------- + // Reads + // --------------------------------------------------------------------- + + /// List flags for a project, newest-key-first, paginated. + /// + /// Returns `(page_of_flags, total_matching_flags)`. + /// + /// Note the two queries rather than one `find_with_related`: a JOIN + /// produces one row per (flag, environment) pair, so paginating it would + /// slice *override rows*, not flags — a flag with three environments would + /// consume three slots and the total would be wrong. Paginate the flags, + /// then fetch their overrides in a single follow-up query (still no N+1). + pub async fn list( + &self, + project_id: i32, + include_archived: bool, + page: Option, + page_size: Option, + ) -> Result<(Vec, u64), FlagError> { + let (page, page_size) = normalize_pagination(page, page_size); + + let mut query = + feature_flags::Entity::find().filter(feature_flags::Column::ProjectId.eq(project_id)); + + if !include_archived { + query = query.filter(feature_flags::Column::ArchivedAt.is_null()); + } + + let paginator = query + .order_by_asc(feature_flags::Column::Key) + .paginate(self.db.as_ref(), page_size); + + let total = paginator.num_items().await?; + let flags = paginator.fetch_page(page - 1).await?; + + if flags.is_empty() { + return Ok((Vec::new(), total)); + } + + let flag_ids: Vec = flags.iter().map(|flag| flag.id).collect(); + let overrides = feature_flag_environments::Entity::find() + .filter(feature_flag_environments::Column::FlagId.is_in(flag_ids)) + .all(self.db.as_ref()) + .await?; + + let mut by_flag: HashMap> = HashMap::new(); + for row in overrides { + by_flag.entry(row.flag_id).or_default().push(row); + } + + let entries = flags + .into_iter() + .map(|flag| { + let environments = by_flag.remove(&flag.id).unwrap_or_default(); + FlagWithEnvironments { flag, environments } + }) + .collect(); + + Ok((entries, total)) + } + + pub async fn get(&self, project_id: i32, key: &str) -> Result { + let flag = feature_flags::Entity::find() + .filter(feature_flags::Column::ProjectId.eq(project_id)) + .filter(feature_flags::Column::Key.eq(key)) + .one(self.db.as_ref()) + .await? + .ok_or_else(|| FlagError::NotFound { + project_id, + key: key.to_string(), + })?; + + let environments = feature_flag_environments::Entity::find() + .filter(feature_flag_environments::Column::FlagId.eq(flag.id)) + .all(self.db.as_ref()) + .await?; + + Ok(FlagWithEnvironments { flag, environments }) + } + + // --------------------------------------------------------------------- + // Writes + // --------------------------------------------------------------------- + + pub async fn create( + &self, + project_id: i32, + request: CreateFlag, + ) -> Result { + Self::validate_key(&request.key)?; + Self::validate_description(&request.key, &request.description)?; + Self::validate_value( + &request.key, + request.value_type, + &request.default_value, + "default_value", + )?; + + let existing = feature_flags::Entity::find() + .filter(feature_flags::Column::ProjectId.eq(project_id)) + .filter(feature_flags::Column::Key.eq(&request.key)) + .one(self.db.as_ref()) + .await?; + if existing.is_some() { + return Err(FlagError::DuplicateKey { + project_id, + key: request.key, + }); + } + + let model = feature_flags::ActiveModel { + project_id: Set(project_id), + key: Set(request.key.clone()), + value_type: Set(request.value_type.as_str().to_string()), + default_value: Set(request.default_value), + description: Set(request.description), + salt: Set(Self::generate_salt()), + client_visible: Set(request.client_visible), + archived_at: Set(None), + ..Default::default() + } + .insert(self.db.as_ref()) + .await?; + + info!( + project_id, + flag_key = %request.key, + value_type = request.value_type.as_str(), + "Created feature flag" + ); + + Ok(model) + } + + pub async fn update( + &self, + project_id: i32, + key: &str, + request: UpdateFlag, + ) -> Result { + let existing = self.get(project_id, key).await?.flag; + + let value_type = FlagValueType::parse(&existing.value_type).ok_or_else(|| { + FlagError::InvalidValueType { + key: key.to_string(), + value_type: existing.value_type.clone(), + } + })?; + + let mut active: feature_flags::ActiveModel = existing.into(); + + if let Some(default_value) = request.default_value { + Self::validate_value(key, value_type, &default_value, "default_value")?; + active.default_value = Set(default_value); + } + if let Some(description) = request.description { + Self::validate_description(key, &description)?; + active.description = Set(description); + } + if let Some(client_visible) = request.client_visible { + active.client_visible = Set(client_visible); + } + + let model = active.update(self.db.as_ref()).await?; + + info!(project_id, flag_key = %key, "Updated feature flag"); + + Ok(model) + } + + /// Archive a flag. Deliberately a soft delete: an archived flag evaluates + /// as `FLAG_NOT_FOUND`, so callers fall back to the default they compiled + /// in rather than silently flipping behaviour. + pub async fn archive( + &self, + project_id: i32, + key: &str, + ) -> Result { + let existing = self.get(project_id, key).await?.flag; + + let mut active: feature_flags::ActiveModel = existing.into(); + active.archived_at = Set(Some(chrono::Utc::now())); + + let model = active.update(self.db.as_ref()).await?; + + info!(project_id, flag_key = %key, "Archived feature flag"); + + Ok(model) + } + + /// Set (or clear) the value of a flag in one environment, and/or flip the + /// kill switch. + pub async fn set_environment_value( + &self, + project_id: i32, + key: &str, + environment_id: i32, + request: SetEnvironmentValue, + ) -> Result { + let flag = self.get(project_id, key).await?.flag; + + let value_type = + FlagValueType::parse(&flag.value_type).ok_or_else(|| FlagError::InvalidValueType { + key: key.to_string(), + value_type: flag.value_type.clone(), + })?; + + // A flag may only be overridden in an environment of its own project. + // Without this a caller who can write project A's flags could attach a + // value to project B's environment. + let environment = environments::Entity::find_by_id(environment_id) + .one(self.db.as_ref()) + .await? + .ok_or(FlagError::EnvironmentNotFound { environment_id })?; + if environment.project_id != project_id { + return Err(FlagError::EnvironmentNotInProject { + project_id, + environment_id, + }); + } + + if let Some(Some(value)) = &request.value { + Self::validate_value(key, value_type, value, "value")?; + } + + let txn = self.db.begin().await?; + + let existing = feature_flag_environments::Entity::find() + .filter(feature_flag_environments::Column::FlagId.eq(flag.id)) + .filter(feature_flag_environments::Column::EnvironmentId.eq(environment_id)) + .one(&txn) + .await?; + + let model = match existing { + Some(row) => { + let mut active: feature_flag_environments::ActiveModel = row.into(); + if let Some(value) = request.value { + active.value = Set(value); + } + if let Some(enabled) = request.enabled { + active.enabled = Set(enabled); + } + active.update(&txn).await? + } + None => { + feature_flag_environments::ActiveModel { + flag_id: Set(flag.id), + environment_id: Set(environment_id), + enabled: Set(request.enabled.unwrap_or(true)), + value: Set(request.value.flatten()), + // Phase 1 never writes rules. The column exists so targeting + // can land without a migration or a resolution-order change. + rules: Set(serde_json::json!([])), + ..Default::default() + } + .insert(&txn) + .await? + } + }; + + txn.commit().await?; + + info!( + project_id, + flag_key = %key, + environment_id, + enabled = model.enabled, + "Set feature flag environment value" + ); + + Ok(model) + } + + // --------------------------------------------------------------------- + // Delivery + // --------------------------------------------------------------------- + + /// Every flag for one environment, already collapsed to what the evaluator + /// needs. This is what the SDK caches in memory. + /// + /// Archived flags are excluded so they resolve to `FLAG_NOT_FOUND` in the + /// SDK and the caller's own fallback wins. + pub async fn snapshot( + &self, + project_id: i32, + environment_id: i32, + client_visible_only: bool, + ) -> Result, FlagError> { + let environment = environments::Entity::find_by_id(environment_id) + .one(self.db.as_ref()) + .await? + .ok_or(FlagError::EnvironmentNotFound { environment_id })?; + if environment.project_id != project_id { + return Err(FlagError::EnvironmentNotInProject { + project_id, + environment_id, + }); + } + + let mut query = feature_flags::Entity::find() + .filter(feature_flags::Column::ProjectId.eq(project_id)) + .filter(feature_flags::Column::ArchivedAt.is_null()); + + if client_visible_only { + query = query.filter(feature_flags::Column::ClientVisible.eq(true)); + } + + // One JOIN, not one query per flag. + let rows = query + .find_with_related(feature_flag_environments::Entity) + .order_by_asc(feature_flags::Column::Key) + .all(self.db.as_ref()) + .await?; + + let snapshots = rows + .into_iter() + .filter_map(|(flag, overrides)| { + collapse_to_environment(flag, overrides, environment_id) + }) + .collect(); + + Ok(snapshots) + } +} + +/// Normalize caller-supplied pagination into `(page, page_size)`. +/// +/// Shared with the handler on purpose: if the handler re-derived the clamp to +/// compute `total_pages`, a request for `page_size=1000` would be served 100 +/// rows while being told the pages were 1000 wide. +pub fn normalize_pagination(page: Option, page_size: Option) -> (u64, u64) { + let page = page.unwrap_or(1).max(1); + let page_size = page_size + .unwrap_or(DEFAULT_PAGE_SIZE) + .clamp(1, MAX_PAGE_SIZE); + (page, page_size) +} + +/// Collapse one flag plus all of its override rows down to what the evaluator +/// needs for a single environment. +/// +/// Free function rather than a method so it can be exercised directly: this is +/// where "no override row means live-and-inheriting" and "an unparsable stored +/// type is dropped" are decided, and both are easy to get wrong. +/// +/// Returns `None` for a flag whose stored `value_type` no longer parses — data +/// corruption. Dropping it makes the SDK report `FLAG_NOT_FOUND` so the +/// caller's own fallback wins, which beats serving a wrongly-typed value. +fn collapse_to_environment( + flag: feature_flags::Model, + overrides: Vec, + environment_id: i32, +) -> Option { + let Some(value_type) = FlagValueType::parse(&flag.value_type) else { + debug!( + flag_key = %flag.key, + value_type = %flag.value_type, + "Skipping feature flag with unrecognised value_type" + ); + return None; + }; + + let this_environment = overrides + .into_iter() + .find(|row| row.environment_id == environment_id); + + let (enabled, environment_value) = match this_environment { + Some(row) => (row.enabled, row.value), + // No override row: the flag is live and inherits its default. + None => (true, None), + }; + + Some(FlagSnapshot { + key: flag.key, + value_type, + default_value: flag.default_value, + enabled, + environment_value, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + use sea_orm::{DatabaseBackend, MockDatabase}; + + // ===================================================================== + // Fixtures + // ===================================================================== + + fn now() -> chrono::DateTime { + chrono::Utc::now() + } + + fn flag_model(id: i32, project_id: i32, key: &str, value_type: &str) -> feature_flags::Model { + feature_flags::Model { + id, + project_id, + key: key.to_string(), + value_type: value_type.to_string(), + default_value: serde_json::json!(false), + description: None, + salt: "a1b2c3".to_string(), + client_visible: false, + archived_at: None, + created_at: now(), + updated_at: now(), + } + } + + fn override_model( + flag_id: i32, + environment_id: i32, + enabled: bool, + value: Option, + ) -> feature_flag_environments::Model { + feature_flag_environments::Model { + id: 1, + flag_id, + environment_id, + enabled, + value, + rules: serde_json::json!([]), + created_at: now(), + updated_at: now(), + } + } + + fn environment_model(id: i32, project_id: i32) -> environments::Model { + environments::Model { + id, + name: "production".to_string(), + slug: "production".to_string(), + subdomain: "prod".to_string(), + last_deployment: None, + host: "example.test".to_string(), + upstreams: Default::default(), + created_at: now(), + updated_at: now(), + project_id, + current_deployment_id: None, + branch: None, + deleted_at: None, + deployment_config: None, + is_preview: false, + protected: false, + sleeping: false, + attack_mode: None, + last_activity_at: None, + force_https: None, + } + } + + fn service_with(db: MockDatabase) -> FlagService { + FlagService::new(Arc::new(db.into_connection())) + } + + // ===================================================================== + // Tenant isolation + // + // These are the highest-value tests in the crate: without them, the only + // thing standing between project A and project B's environments is a + // comparison nobody is watching. + // ===================================================================== + + #[tokio::test] + async fn set_environment_value_rejects_an_environment_from_another_project() { + let db = MockDatabase::new(DatabaseBackend::Postgres) + // get(): the flag, then its (empty) override rows. + .append_query_results([vec![flag_model(1, 1, "checkout.v2", "bool")]]) + .append_query_results([Vec::::new()]) + // The environment lookup returns an environment owned by project 2. + .append_query_results([vec![environment_model(9, 2)]]); + + let result = service_with(db) + .set_environment_value(1, "checkout.v2", 9, SetEnvironmentValue::default()) + .await; + + assert!( + matches!( + result, + Err(FlagError::EnvironmentNotInProject { + project_id: 1, + environment_id: 9 + }) + ), + "a flag must not be attachable to another project's environment" + ); + } + + #[tokio::test] + async fn snapshot_rejects_an_environment_from_another_project() { + let db = MockDatabase::new(DatabaseBackend::Postgres) + .append_query_results([vec![environment_model(9, 2)]]); + + let result = service_with(db).snapshot(1, 9, false).await; + + assert!( + matches!( + result, + Err(FlagError::EnvironmentNotInProject { + project_id: 1, + environment_id: 9 + }) + ), + "a token for project 1 must not read project 2's environment" + ); + } + + #[tokio::test] + async fn snapshot_rejects_a_missing_environment() { + let db = MockDatabase::new(DatabaseBackend::Postgres) + .append_query_results([Vec::::new()]); + + assert!(matches!( + service_with(db).snapshot(1, 404, false).await, + Err(FlagError::EnvironmentNotFound { + environment_id: 404 + }) + )); + } + + #[tokio::test] + async fn set_environment_value_rejects_a_missing_environment() { + let db = MockDatabase::new(DatabaseBackend::Postgres) + .append_query_results([vec![flag_model(1, 1, "checkout.v2", "bool")]]) + .append_query_results([Vec::::new()]) + .append_query_results([Vec::::new()]); + + assert!(matches!( + service_with(db) + .set_environment_value(1, "checkout.v2", 404, SetEnvironmentValue::default()) + .await, + Err(FlagError::EnvironmentNotFound { + environment_id: 404 + }) + )); + } + + // ===================================================================== + // CRUD error paths + // ===================================================================== + + #[tokio::test] + async fn get_returns_not_found_with_the_key_that_was_searched_for() { + let db = MockDatabase::new(DatabaseBackend::Postgres) + .append_query_results([Vec::::new()]); + + let Err(FlagError::NotFound { project_id, key }) = + service_with(db).get(7, "missing.flag").await + else { + panic!("expected NotFound"); + }; + assert_eq!(project_id, 7); + assert_eq!(key, "missing.flag"); + } + + #[tokio::test] + async fn create_rejects_a_duplicate_key() { + let db = MockDatabase::new(DatabaseBackend::Postgres) + // The existence probe finds a flag already using this key. + .append_query_results([vec![flag_model(1, 1, "checkout.v2", "bool")]]); + + let result = service_with(db) + .create( + 1, + CreateFlag { + key: "checkout.v2".to_string(), + value_type: FlagValueType::Bool, + default_value: serde_json::json!(false), + description: None, + client_visible: false, + }, + ) + .await; + + assert!(matches!(result, Err(FlagError::DuplicateKey { .. }))); + } + + /// Validation must run before the database is touched, so a bad key is a + /// 400 rather than an opaque insert failure. + #[tokio::test] + async fn create_rejects_an_invalid_key_without_querying() { + let db = MockDatabase::new(DatabaseBackend::Postgres); + + let result = service_with(db) + .create( + 1, + CreateFlag { + key: "Checkout/V2".to_string(), + value_type: FlagValueType::Bool, + default_value: serde_json::json!(false), + description: None, + client_visible: false, + }, + ) + .await; + + assert!(matches!(result, Err(FlagError::InvalidKey { .. }))); + } + + #[tokio::test] + async fn create_rejects_a_default_that_does_not_match_the_declared_type() { + let db = MockDatabase::new(DatabaseBackend::Postgres); + + let result = service_with(db) + .create( + 1, + CreateFlag { + key: "checkout.v2".to_string(), + value_type: FlagValueType::Bool, + default_value: serde_json::json!("yes"), + description: None, + client_visible: false, + }, + ) + .await; + + assert!(matches!( + result, + Err(FlagError::ValueTypeMismatch { field, .. }) if field == "default_value" + )); + } + + // ===================================================================== + // Snapshot collapsing + // ===================================================================== + + #[test] + fn collapse_inherits_the_default_when_no_override_row_exists() { + let snapshot = + collapse_to_environment(flag_model(1, 1, "checkout.v2", "bool"), vec![], 1).unwrap(); + + assert!(snapshot.enabled, "a flag with no override row is live"); + assert_eq!(snapshot.environment_value, None); + } + + #[test] + fn collapse_uses_only_the_requested_environments_override() { + let snapshot = collapse_to_environment( + flag_model(1, 1, "checkout.v2", "bool"), + vec![ + override_model(1, 2, true, Some(serde_json::json!(true))), + override_model(1, 3, false, Some(serde_json::json!(false))), + ], + 2, + ) + .unwrap(); + + assert!(snapshot.enabled); + assert_eq!(snapshot.environment_value, Some(serde_json::json!(true))); + } + + /// The kill switch must survive into the snapshot with the override intact, + /// so re-enabling restores the previous value rather than losing it. + #[test] + fn collapse_preserves_the_override_while_disabled() { + let snapshot = collapse_to_environment( + flag_model(1, 1, "checkout.v2", "bool"), + vec![override_model(1, 2, false, Some(serde_json::json!(true)))], + 2, + ) + .unwrap(); + + assert!(!snapshot.enabled); + assert_eq!( + snapshot.environment_value, + Some(serde_json::json!(true)), + "disabling must not discard the stored value" + ); + } + + #[test] + fn collapse_drops_a_flag_with_an_unparsable_stored_type() { + assert!( + collapse_to_environment(flag_model(1, 1, "broken", "wat"), vec![], 1).is_none(), + "corrupt rows must be dropped so the caller's fallback wins" + ); + } + + // ===================================================================== + // Pagination + // ===================================================================== + + #[test] + fn pagination_defaults_to_the_first_page_of_twenty() { + assert_eq!(normalize_pagination(None, None), (1, DEFAULT_PAGE_SIZE)); + } + + #[test] + fn pagination_caps_page_size_and_floors_page() { + assert_eq!(normalize_pagination(Some(3), Some(50)), (3, 50)); + assert_eq!( + normalize_pagination(Some(1), Some(10_000)), + (1, MAX_PAGE_SIZE), + "an unbounded page_size must not be honoured" + ); + assert_eq!(normalize_pagination(Some(0), Some(0)), (1, 1)); + } + + #[test] + fn accepts_conventional_keys() { + assert!(FlagService::validate_key("checkout.v2").is_ok()); + assert!(FlagService::validate_key("new-search").is_ok()); + assert!(FlagService::validate_key("worker_batch_size").is_ok()); + assert!(FlagService::validate_key("a").is_ok()); + assert!(FlagService::validate_key("2fa.enabled").is_ok()); + } + + #[test] + fn rejects_empty_key() { + assert!(matches!( + FlagService::validate_key(""), + Err(FlagError::InvalidKey { .. }) + )); + } + + #[test] + fn rejects_uppercase_and_spaces() { + assert!(FlagService::validate_key("Checkout").is_err()); + assert!(FlagService::validate_key("checkout v2").is_err()); + assert!(FlagService::validate_key("checkout/v2").is_err()); + } + + #[test] + fn rejects_leading_punctuation() { + assert!(FlagService::validate_key(".checkout").is_err()); + assert!(FlagService::validate_key("-checkout").is_err()); + assert!(FlagService::validate_key("_checkout").is_err()); + } + + #[test] + fn rejects_over_length_key() { + let key = "a".repeat(MAX_KEY_LEN + 1); + assert!(matches!( + FlagService::validate_key(&key), + Err(FlagError::InvalidKey { .. }) + )); + assert!(FlagService::validate_key(&"a".repeat(MAX_KEY_LEN)).is_ok()); + } + + #[test] + fn key_error_names_the_offending_character() { + let Err(FlagError::InvalidKey { reason, .. }) = FlagService::validate_key("checkout/v2") + else { + panic!("expected InvalidKey"); + }; + assert!( + reason.contains('/'), + "reason did not name the character: {reason}" + ); + } + + #[test] + fn value_must_match_declared_type() { + assert!(FlagService::validate_value( + "f", + FlagValueType::Bool, + &serde_json::json!(true), + "default_value" + ) + .is_ok()); + + assert!(matches!( + FlagService::validate_value( + "f", + FlagValueType::Bool, + &serde_json::json!("true"), + "default_value" + ), + Err(FlagError::ValueTypeMismatch { .. }) + )); + } + + #[test] + fn rejects_over_length_description() { + let description = Some("x".repeat(MAX_DESCRIPTION_LEN + 1)); + assert!(matches!( + FlagService::validate_description("f", &description), + Err(FlagError::Validation { .. }) + )); + } + + #[test] + fn salts_are_unique_per_flag() { + let a = FlagService::generate_salt(); + let b = FlagService::generate_salt(); + assert_ne!(a, b); + assert_eq!(a.len(), 32); + } +} diff --git a/crates/temps-flags/src/services/mod.rs b/crates/temps-flags/src/services/mod.rs new file mode 100644 index 000000000..5db5c619f --- /dev/null +++ b/crates/temps-flags/src/services/mod.rs @@ -0,0 +1,6 @@ +pub mod flag_service; + +pub use flag_service::{ + normalize_pagination, CreateFlag, FlagService, FlagWithEnvironments, SetEnvironmentValue, + UpdateFlag, +}; From e68c82b0db8b14319c58b2054061adc3a5b4d1fd Mon Sep 17 00:00:00 2001 From: David Viejo Date: Mon, 3 Aug 2026 09:31:26 +0200 Subject: [PATCH 03/12] feat(sdk): add feature flag client to @temps-sdk/node-sdk Lives in the existing package rather than a new one: a separate library would duplicate the same deployment-token bootstrap, and this is a few hundred lines of caching, not a product. Reads are synchronous and cost no network I/O. The whole environment's flag set lives in memory and refreshes in the background, because a per-check HTTP round trip (~200-500ms) is unusable inside a request handler. Zero configuration on Temps: TEMPS_API_URL and TEMPS_API_TOKEN are already injected into every deployment and the token pins the project and environment, so `new FlagsClient()` knows what to fetch. evaluate() is a deliberate line-for-line mirror of the Rust evaluator. If the two diverge the same flag resolves one way in the app and another on the server, so the tests mirror the Rust tests case for case. Failure is never fatal: init() does not throw, a failed refresh keeps the last good snapshot rather than reverting every flag to its fallback, and lastError is exposed so a self-hosted operator can see that flags are stale instead of guessing why a rollout did nothing. --- .../packages/node-sdk/src/flags/client.ts | 216 ++++++++++++++++++ .../node-sdk/src/flags/evaluate.test.ts | 129 +++++++++++ .../packages/node-sdk/src/flags/evaluate.ts | 96 ++++++++ .../node/packages/node-sdk/src/flags/index.ts | 11 + .../node/packages/node-sdk/src/flags/types.ts | 91 ++++++++ sdks/node/packages/node-sdk/src/index.ts | 5 + 6 files changed, 548 insertions(+) create mode 100644 sdks/node/packages/node-sdk/src/flags/client.ts create mode 100644 sdks/node/packages/node-sdk/src/flags/evaluate.test.ts create mode 100644 sdks/node/packages/node-sdk/src/flags/evaluate.ts create mode 100644 sdks/node/packages/node-sdk/src/flags/index.ts create mode 100644 sdks/node/packages/node-sdk/src/flags/types.ts diff --git a/sdks/node/packages/node-sdk/src/flags/client.ts b/sdks/node/packages/node-sdk/src/flags/client.ts new file mode 100644 index 000000000..97678be9d --- /dev/null +++ b/sdks/node/packages/node-sdk/src/flags/client.ts @@ -0,0 +1,216 @@ +/** + * In-memory feature-flag client for services running on Temps. + * + * Reads are synchronous and cost no network I/O: the whole environment's flag + * set lives in memory and is refreshed in the background. That is the point — + * a per-check HTTP round trip (~200-500ms) is unusable in a request handler. + * + * Zero configuration on Temps: `TEMPS_API_URL` and `TEMPS_API_TOKEN` are + * injected into every deployment, and the token pins the project (and usually + * the environment), so `new FlagsClient()` already knows what to fetch. + */ + +import { evaluate } from './evaluate'; +import type { + EvalContext, + Evaluation, + FlagSnapshot, + FlagSnapshotResponse, + FlagsClientOptions, +} from './types'; + +const DEFAULT_REFRESH_INTERVAL_MS = 30_000; +const DEFAULT_TIMEOUT_MS = 5_000; + +/** + * Read an environment variable without depending on Node type definitions. + * + * This package is consumed from browsers too, so `lib` is DOM-flavoured and + * there is no `process` global in the type environment. Going through + * `globalThis` keeps the client usable in both without pulling `@types/node` + * into every consumer. + */ +function envVar(name: string): string | undefined { + const global = globalThis as { process?: { env?: Record } }; + return global.process?.env?.[name]; +} + +export class FlagsClient { + private readonly apiUrl: string; + private readonly apiToken: string; + private readonly environmentId?: number; + private readonly refreshIntervalMs: number; + private readonly timeoutMs: number; + private readonly onError: (error: Error) => void; + + private flags = new Map(); + private etag: string | null = null; + private timer: ReturnType | null = null; + + /** True once a snapshot has been successfully loaded at least once. */ + public ready = false; + /** + * The most recent refresh failure, or `null`. Exposed rather than swallowed: + * a self-hosted operator debugging alone needs to see that flags are stale, + * not guess why a rollout did nothing. + */ + public lastError: Error | null = null; + + constructor(options: FlagsClientOptions = {}) { + this.apiUrl = (options.apiUrl ?? envVar('TEMPS_API_URL') ?? '').replace(/\/+$/, ''); + this.apiToken = options.apiToken ?? envVar('TEMPS_API_TOKEN') ?? ''; + this.environmentId = options.environmentId; + this.refreshIntervalMs = options.refreshIntervalMs ?? DEFAULT_REFRESH_INTERVAL_MS; + this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS; + this.onError = + options.onError ?? + ((error) => { + console.warn(`[temps-flags] ${error.message}`); + }); + } + + /** + * Load the first snapshot and start background refresh. + * + * Never throws. A flag service that is unreachable must not stop an app from + * booting — every `get()` returns its caller-supplied fallback until a + * snapshot arrives, and `ready` stays `false` so you can surface it. + */ + async init(): Promise { + if (!this.apiUrl || !this.apiToken) { + this.fail( + new Error( + 'TEMPS_API_URL and TEMPS_API_TOKEN are required (both are injected automatically for apps deployed on Temps). Flags will serve fallbacks.', + ), + ); + } else { + await this.refresh(); + } + + if (this.timer === null && this.refreshIntervalMs > 0) { + this.timer = setInterval(() => { + void this.refresh(); + }, this.refreshIntervalMs); + // On Node, don't hold the process open just to poll for flags. No-op in + // a browser, where timer handles are plain numbers. + (this.timer as unknown as { unref?: () => void }).unref?.(); + } + } + + /** Stop background refresh. Safe to call more than once. */ + close(): void { + if (this.timer !== null) { + clearInterval(this.timer); + this.timer = null; + } + } + + /** + * Read a flag. Synchronous, in-memory, no network I/O. + * + * `fallback` is returned whenever the flag cannot be resolved — unknown key, + * snapshot not loaded yet, or a stored value that does not match the flag's + * declared type. + */ + get(key: string, context: EvalContext = {}, fallback: T): T { + return this.getDetails(key, context, fallback).value; + } + + /** + * Read a flag along with the reason it resolved that way. + * + * Use this when debugging "why is this user seeing the old checkout?" — the + * reason distinguishes a kill switch from an unset value from a flag that + * does not exist. + */ + getDetails(key: string, context: EvalContext = {}, fallback: T): Evaluation { + return evaluate(this.flags.get(key), context, fallback); + } + + /** Every flag key currently cached. */ + keys(): string[] { + return [...this.flags.keys()]; + } + + /** + * Fetch the snapshot once. + * + * A failure leaves the previous snapshot in place: stale flags are far better + * than every flag suddenly reverting to its fallback because the control + * plane blinked. + */ + async refresh(): Promise { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), this.timeoutMs); + + try { + const url = new URL(`${this.apiUrl}/flags/snapshot`); + if (this.environmentId !== undefined) { + url.searchParams.set('environment_id', String(this.environmentId)); + } + + const headers: Record = { + Authorization: `Bearer ${this.apiToken}`, + Accept: 'application/json', + }; + if (this.etag) { + headers['If-None-Match'] = this.etag; + } + + const response = await fetch(url, { headers, signal: controller.signal }); + + // Nothing changed since the last poll — the common case. + if (response.status === 304) { + this.lastError = null; + return; + } + + if (!response.ok) { + this.fail( + new Error( + `Flag snapshot request failed: ${response.status} ${response.statusText}. Serving ${this.ready ? 'the last known' : 'fallback'} values.`, + ), + ); + return; + } + + const body = (await response.json()) as FlagSnapshotResponse; + + const next = new Map(); + for (const flag of body.flags ?? []) { + next.set(flag.key, flag); + } + + this.flags = next; + this.etag = response.headers.get('etag'); + this.ready = true; + this.lastError = null; + } catch (error) { + const reason = error instanceof Error ? error.message : String(error); + this.fail( + new Error( + `Flag snapshot request failed: ${reason}. Serving ${this.ready ? 'the last known' : 'fallback'} values.`, + ), + ); + } finally { + clearTimeout(timeout); + } + } + + private fail(error: Error): void { + this.lastError = error; + this.onError(error); + } +} + +/** + * Process-wide client, for the common case where an app has one flag set. + * + * ```ts + * import { flags } from '@temps-sdk/node-sdk'; + * + * await flags.init(); + * if (flags.get('checkout.v2', { key: user.id }, false)) { ... } + * ``` + */ +export const flags = new FlagsClient(); diff --git a/sdks/node/packages/node-sdk/src/flags/evaluate.test.ts b/sdks/node/packages/node-sdk/src/flags/evaluate.test.ts new file mode 100644 index 000000000..f13a03f12 --- /dev/null +++ b/sdks/node/packages/node-sdk/src/flags/evaluate.test.ts @@ -0,0 +1,129 @@ +import { describe, expect, it } from 'vitest'; +import { evaluate, valueMatchesType } from './evaluate'; +import type { FlagSnapshot } from './types'; + +/** + * These mirror the Rust tests in `crates/temps-flags/src/eval.rs`. The SDK + * evaluates locally, so any divergence means the same flag resolves one way in + * the app and another on the server. + */ + +function snapshot(enabled: boolean, environmentValue: unknown | null): FlagSnapshot { + return { + key: 'checkout.v2', + value_type: 'bool', + default_value: false, + enabled, + environment_value: environmentValue, + }; +} + +describe('evaluate', () => { + it('serves the environment value when set', () => { + const result = evaluate(snapshot(true, true), {}, false); + + expect(result.value).toBe(true); + expect(result.reason).toEqual({ kind: 'ENVIRONMENT_VALUE' }); + expect(result.variant).toBeNull(); + }); + + it('falls back to the flag default when no environment value is set', () => { + const result = evaluate(snapshot(true, null), {}, true); + + expect(result.value).toBe(false); + expect(result.reason).toEqual({ kind: 'DEFAULT' }); + }); + + it('returns the caller fallback for an unknown flag', () => { + const result = evaluate(undefined, {}, 'my-fallback'); + + expect(result.value).toBe('my-fallback'); + expect(result.reason).toEqual({ kind: 'FLAG_NOT_FOUND' }); + }); + + // The kill switch must outrank the environment value, or "disable this flag" + // would not disable a flag that has an override set. + it('lets the kill switch beat the environment value', () => { + const result = evaluate(snapshot(false, true), {}, true); + + expect(result.value).toBe(false); + expect(result.reason).toEqual({ kind: 'DISABLED' }); + }); + + // Asserted explicitly so that the day targeting lands, this test fails and + // forces a conscious update rather than silently changing behaviour. + it('ignores context in phase 1', () => { + const flag = snapshot(true, true); + + const withContext = evaluate(flag, { key: 'user_1001', attributes: { plan: 'free' } }, false); + const withoutContext = evaluate(flag, {}, false); + + expect(withContext).toEqual(withoutContext); + }); + + it('degrades a type-mismatched value to the flag default', () => { + const result = evaluate(snapshot(true, 'yes'), {}, true); + + expect(result.value).toBe(false); + expect(result.reason).toEqual({ kind: 'ERROR' }); + }); + + it('is total even when the default is also invalid', () => { + const flag: FlagSnapshot = { + key: 'broken', + value_type: 'number', + default_value: 'not a number', + enabled: true, + environment_value: 'also not a number', + }; + + const result = evaluate(flag, {}, 42); + + expect(result.value).toBe(42); + expect(result.reason).toEqual({ kind: 'ERROR' }); + }); + + it('supports non-boolean flag types', () => { + const flag: FlagSnapshot = { + key: 'worker.batch_size', + value_type: 'number', + default_value: 50, + enabled: true, + environment_value: 200, + }; + + expect(evaluate(flag, {}, 0).value).toBe(200); + }); + + it('treats an undefined environment value the same as null', () => { + const flag: FlagSnapshot = { + key: 'checkout.v2', + value_type: 'bool', + default_value: false, + enabled: true, + }; + + expect(evaluate(flag, {}, true).reason).toEqual({ kind: 'DEFAULT' }); + }); +}); + +describe('valueMatchesType', () => { + it('matches declared types', () => { + expect(valueMatchesType('bool', true)).toBe(true); + expect(valueMatchesType('bool', 1)).toBe(false); + expect(valueMatchesType('number', 1.5)).toBe(true); + expect(valueMatchesType('number', '1.5')).toBe(false); + expect(valueMatchesType('string', 'x')).toBe(true); + expect(valueMatchesType('json', { a: 1 })).toBe(true); + }); + + it('never accepts null, which is indistinguishable from unset', () => { + expect(valueMatchesType('json', null)).toBe(false); + expect(valueMatchesType('bool', null)).toBe(false); + }); + + it('rejects NaN and Infinity, which do not survive JSON', () => { + expect(valueMatchesType('number', NaN)).toBe(false); + expect(valueMatchesType('number', Infinity)).toBe(false); + }); +}); diff --git a/sdks/node/packages/node-sdk/src/flags/evaluate.ts b/sdks/node/packages/node-sdk/src/flags/evaluate.ts new file mode 100644 index 000000000..8c7f85869 --- /dev/null +++ b/sdks/node/packages/node-sdk/src/flags/evaluate.ts @@ -0,0 +1,96 @@ +/** + * Flag evaluation. Pure, synchronous, total — no I/O, never throws. + * + * This is a deliberate line-for-line mirror of `evaluate()` in + * `crates/temps-flags/src/eval.rs`. If you change the resolution order here, + * change it there in the same commit, or the same flag will resolve + * differently in the app and on the server. + * + * Resolution order: + * + * 1. flag missing or archived -> caller's fallback FLAG_NOT_FOUND + * 2. enabled === false -> default_value DISABLED + * 3. -- reserved for rules -- RULE_MATCH{i} + * | PERCENTAGE_ROLLOUT{i} + * 4. environment value present -> that value ENVIRONMENT_VALUE + * 5. otherwise -> default_value DEFAULT + */ + +import type { EvalContext, Evaluation, FlagSnapshot, FlagValueType } from './types'; + +/** + * Whether a concrete JSON value is admissible for a declared flag type. + * + * `json` accepts anything except `null`: a flag must always resolve to + * something usable, and `null` is indistinguishable from "unset". + */ +export function valueMatchesType(valueType: FlagValueType, value: unknown): boolean { + switch (valueType) { + case 'bool': + return typeof value === 'boolean'; + case 'string': + return typeof value === 'string'; + case 'number': + return typeof value === 'number' && Number.isFinite(value); + case 'json': + return value !== null && value !== undefined; + default: + return false; + } +} + +function outcome(value: unknown, reason: Evaluation['reason']): Evaluation { + return { value: value as T, variant: null, reason }; +} + +/** + * Serve `value` if it matches the flag's declared type, otherwise degrade to + * the flag default. An operator typing the wrong thing into the flag UI must + * not break the running app. + */ +function sanitized( + flag: FlagSnapshot, + value: unknown, + reason: Evaluation['reason'], + fallback: T, +): Evaluation { + if (valueMatchesType(flag.value_type, value)) { + return outcome(value, reason); + } + if (valueMatchesType(flag.value_type, flag.default_value)) { + return outcome(flag.default_value, { kind: 'ERROR' }); + } + return outcome(fallback, { kind: 'ERROR' }); +} + +/** + * Evaluate one flag. Always returns a usable value. + * + * `_context` is accepted and ignored: targeting has not shipped. The parameter + * is the expensive half of the contract; the code that reads it is cheap. + */ +export function evaluate( + flag: FlagSnapshot | undefined, + _context: EvalContext, + fallback: T, +): Evaluation { + if (!flag) { + return outcome(fallback, { kind: 'FLAG_NOT_FOUND' }); + } + + if (!flag.enabled) { + return sanitized(flag, flag.default_value, { kind: 'DISABLED' }, fallback); + } + + // ------------------------------------------------------------------------- + // Step 3: targeting rules evaluate HERE, ahead of the environment value and + // behind the kill switch. Nothing above or below this point changes when + // they land. + // ------------------------------------------------------------------------- + + if (flag.environment_value !== null && flag.environment_value !== undefined) { + return sanitized(flag, flag.environment_value, { kind: 'ENVIRONMENT_VALUE' }, fallback); + } + + return sanitized(flag, flag.default_value, { kind: 'DEFAULT' }, fallback); +} diff --git a/sdks/node/packages/node-sdk/src/flags/index.ts b/sdks/node/packages/node-sdk/src/flags/index.ts new file mode 100644 index 000000000..f8be97139 --- /dev/null +++ b/sdks/node/packages/node-sdk/src/flags/index.ts @@ -0,0 +1,11 @@ +export { FlagsClient, flags } from './client'; +export { evaluate, valueMatchesType } from './evaluate'; +export type { + EvalContext, + EvalReason, + Evaluation, + FlagSnapshot, + FlagSnapshotResponse, + FlagValueType, + FlagsClientOptions, +} from './types'; diff --git a/sdks/node/packages/node-sdk/src/flags/types.ts b/sdks/node/packages/node-sdk/src/flags/types.ts new file mode 100644 index 000000000..60bdc38ab --- /dev/null +++ b/sdks/node/packages/node-sdk/src/flags/types.ts @@ -0,0 +1,91 @@ +/** + * Feature-flag types. These mirror `crates/temps-flags/src/eval.rs` exactly — + * the SDK evaluates locally, so the two implementations must agree or the same + * flag resolves differently on the server and in the app. + */ + +export type FlagValueType = 'bool' | 'string' | 'number' | 'json'; + +/** + * Why an evaluation produced the value it did. + * + * `RULE_MATCH` and `PERCENTAGE_ROLLOUT` are declared because they are part of + * the wire contract, but the server never emits them yet — targeting has not + * shipped. Code that switches on `reason` should handle them from day one. + */ +export type EvalReason = + | { kind: 'FLAG_NOT_FOUND' } + | { kind: 'DISABLED' } + | { kind: 'RULE_MATCH'; index: number } + | { kind: 'PERCENTAGE_ROLLOUT'; index: number } + | { kind: 'ENVIRONMENT_VALUE' } + | { kind: 'DEFAULT' } + | { kind: 'ERROR' }; + +/** One flag, already resolved down to a single environment. */ +export interface FlagSnapshot { + key: string; + value_type: FlagValueType; + default_value: unknown; + /** `false` means the kill switch is engaged for this environment. */ + enabled: boolean; + /** `null` means "inherit `default_value`". */ + environment_value?: unknown | null; +} + +export interface FlagSnapshotResponse { + environment_id: number; + flags: FlagSnapshot[]; +} + +/** + * Everything you know about the subject being evaluated. + * + * Accepted and ignored today: targeting has not shipped. It is in the signature + * now so that when it does, you add attributes to a call you have already + * written instead of editing every call site. + */ +export interface EvalContext { + /** Stable bucketing subject (user id, account id, device id). */ + key?: string; + /** Targeting attributes, e.g. `{ plan: 'enterprise', region: 'eu' }`. */ + attributes?: Record; +} + +export interface Evaluation { + value: T; + /** Named variant, once variants exist. Always `null` today. */ + variant: string | null; + reason: EvalReason; +} + +export interface FlagsClientOptions { + /** + * Control-plane API base URL. Defaults to `TEMPS_API_URL`, which Temps + * injects into every deployment. + */ + apiUrl?: string; + /** + * Deployment token. Defaults to `TEMPS_API_TOKEN`, injected alongside + * `TEMPS_API_URL`. + */ + apiToken?: string; + /** + * Only needed when the token is project-wide rather than scoped to one + * environment. + */ + environmentId?: number; + /** + * Background refresh interval in milliseconds. Default 30s. Unchanged flags + * cost a 304, not a payload. + */ + refreshIntervalMs?: number; + /** Per-request timeout in milliseconds. Default 5s. */ + timeoutMs?: number; + /** + * Called when a background refresh fails. Defaults to a `console.warn`. + * Failures never throw and never clear the cache — the last good snapshot + * keeps serving. + */ + onError?: (error: Error) => void; +} diff --git a/sdks/node/packages/node-sdk/src/index.ts b/sdks/node/packages/node-sdk/src/index.ts index 39eadf3a1..946c203a3 100644 --- a/sdks/node/packages/node-sdk/src/index.ts +++ b/sdks/node/packages/node-sdk/src/index.ts @@ -6,6 +6,11 @@ export * from './client/types.gen'; export * from './client/sdk.gen'; export * as ErrorTracking from './errors'; +// Feature flags. Lives in this package rather than a separate one: it shares +// the deployment-token bootstrap and would otherwise duplicate it. +export * as Flags from './flags'; +export { FlagsClient, flags } from './flags'; + export interface TempsClientConfig { baseUrl: string; apiKey?: string; From 02723a886a153d26e16688197db9787d1136182c Mon Sep 17 00:00:00 2001 From: David Viejo Date: Mon, 3 Aug 2026 09:31:52 +0200 Subject: [PATCH 04/12] feat(cli): add temps flags commands Full parity with the flags API, in the TypeScript client rather than the Rust binary: apps/temps-cli is the one scripting surface for the API, and the Rust binary's subcommands are server lifecycle commands. temps flags list|get|create|update|set|clear|disable|enable|archive `flags set` reads the flag first so the raw CLI string is parsed into the flag's own declared type - a shell has no types to offer, and the server rejects a mismatch. `flags disable` is the kill switch as a single command. Also registers flags with the docs generator, which uses a hardcoded import list, so the commands actually appear in CLI.md/CLI.mdx. Regenerating those picked up pre-existing drift for other commands as well. --- apps/temps-cli/docs/CLI.md | 1754 +++++++++++++++++--- apps/temps-cli/docs/CLI.mdx | 1448 +++++++++++++--- apps/temps-cli/openapi.json | 2 +- apps/temps-cli/scripts/generate-docs.ts | 2 + apps/temps-cli/src/api/index.ts | 4 +- apps/temps-cli/src/api/sdk.gen.ts | 71 +- apps/temps-cli/src/api/types.gen.ts | 505 ++++++ apps/temps-cli/src/cli.ts | 2 + apps/temps-cli/src/commands/flags/index.ts | 557 +++++++ 9 files changed, 3900 insertions(+), 445 deletions(-) create mode 100644 apps/temps-cli/src/commands/flags/index.ts diff --git a/apps/temps-cli/docs/CLI.md b/apps/temps-cli/docs/CLI.md index ed3e2f19b..5a71a5d2d 100644 --- a/apps/temps-cli/docs/CLI.md +++ b/apps/temps-cli/docs/CLI.md @@ -2,7 +2,7 @@ > Auto-generated documentation for the Temps CLI. > -> Generated on: 2026-01-02 +> Generated on: 2026-08-03 ## Installation @@ -33,94 +33,85 @@ bunx @temps-sdk/cli configure ## Commands -## `login` +## `projects` (alias: `project`, `p`) -Authenticate with Temps using an API key +Manage projects -**Options:** +**Subcommands:** -| Flag | Description | Default | Required | -|------|-------------|---------|----------| -| `-k, --api-key ` | API key (will prompt if not provided) | - | Yes | +- `secrets` - Manage project secrets — mounted into the deployed container as files at /run/secrets/ (mode 0400), not environment variables. Distinct from `temps secrets` (agent/MCP-sandbox-scoped). +- `list` (`ls`) - List all projects +- `create` (`new`) - Create a new project (git-based or manual deployment) +- `show` (`get`) - Show project details +- `update` (`edit`) - Update project name and description +- `settings` - Update project settings (slug, attack mode, preview environments) +- `git` - Update git repository settings +- `config` - Update deployment configuration (resources, replicas) +- `delete` (`rm`) - Delete a project + +### `projects secrets` -## `logout` +Manage project secrets — mounted into the deployed container as files at /run/secrets/ (mode 0400), not environment variables. Distinct from `temps secrets` (agent/MCP-sandbox-scoped). + +**Subcommands:** -Log out and clear credentials +- `list` (`ls`) - List secrets for a project (values are never returned) +- `create` (`add`) - Create a project secret (mounted at /run/secrets/ on the next deployment) +- `update` - Update a project secret (a redeploy is required for running containers to pick it up) +- `delete` (`rm`) - Delete a project secret -## `whoami` +#### `projects secrets list` (alias: `ls`) -Display current authenticated user +List secrets for a project (values are never returned) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output as JSON | - | No | +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Filter to one environment | - | Yes | +| `--json` | Output in JSON format | - | No | -## `configure` +#### `projects secrets create` (alias: `add`) -Configure CLI settings (AWS-style wizard) +Create a project secret (mounted at /run/secrets/ on the next deployment) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--api-url ` | API URL | - | Yes | -| `--api-token ` | API token for authentication | - | Yes | -| `--output-format ` | Output format (table, json, minimal) | - | Yes | -| `--enable-colors` | Enable colored output in config | - | No | -| `--disable-colors` | Disable colored output in config | - | No | -| `-i, --interactive` | Force interactive mode even in non-TTY | - | No | -| `-y, --no-interactive` | Non-interactive mode (uses defaults for unspecified options) | - | No | - -**Subcommands:** - -- `get` - Get a configuration value -- `set` - Set a configuration value -- `list` - List all configuration values -- `show` - Show current configuration and authentication status -- `reset` - Reset configuration to defaults - -### `configure get` - -Get a configuration value - -### `configure set` - -Set a configuration value - -### `configure list` - -List all configuration values +| `-p, --project ` | Project slug or ID | - | Yes | +| `-k, --key ` | Secret key — becomes the filename at /run/secrets/. Letters, digits, underscore; must start with a letter or underscore. | - | Yes | +| `-v, --value ` | Secret value (<=1 MiB). Prefix with @ to read from a local file, e.g. @./auth.json — never touches shell history. | - | Yes | +| `-e, --environment ` | Scope to one environment (repeatable; default: all) | `` | Yes | +| `--include-in-preview` | Also mount this secret in preview environments | - | No | -### `configure show` +#### `projects secrets update` -Show current configuration and authentication status +Update a project secret (a redeploy is required for running containers to pick it up) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output in JSON format | - | No | - -### `configure reset` - -Reset configuration to defaults +| `-p, --project ` | Project slug or ID | - | Yes | +| `-k, --key ` | Key of the secret to update | - | Yes | +| `-v, --value ` | New value (<=1 MiB). Prefix with @ to read from a local file. Omit to keep the existing value. | - | Yes | +| `-e, --environment ` | Replace environment scoping (repeatable) | `` | Yes | +| `--include-in-preview` | Include in preview environments | - | No | +| `--no-include-in-preview` | Exclude from preview environments | - | No | -## `projects` (alias: `project`, `p`) +#### `projects secrets delete` (alias: `rm`) -Manage projects +Delete a project secret -**Subcommands:** +**Options:** -- `list` (`ls`) - List all projects -- `create` (`new`) - Create a new project -- `show` (`get`) - Show project details -- `update` (`edit`) - Update project name and description -- `settings` - Update project settings (slug, attack mode, preview environments) -- `git` - Update git repository settings -- `config` - Update deployment configuration (resources, replicas) -- `delete` (`rm`) - Delete a project +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation (alias for --force) | - | No | ### `projects list` (alias: `ls`) @@ -131,10 +122,12 @@ List all projects | Flag | Description | Default | Required | |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | +| `--page ` | Page number | - | Yes | +| `--per-page ` | Items per page | - | Yes | ### `projects create` (alias: `new`) -Create a new project +Create a new project (git-based or manual deployment) **Options:** @@ -142,7 +135,16 @@ Create a new project |------|-------------|---------|----------| | `-n, --name ` | Project name | - | Yes | | `-d, --description ` | Project description | - | Yes | -| `--repo ` | Git repository URL | - | Yes | +| `--repo ` | Repository in owner/name format (nested groups supported: group/subgroup/name) | - | Yes | +| `--branch ` | Git branch | - | Yes | +| `--directory ` | Root directory (relative to repo) | - | Yes | +| `--preset ` | Build preset (e.g., nextjs, nodejs, static, docker) | - | Yes | +| `--connection ` | Git connection ID | - | Yes | +| `--manual` | Create a manual (non-git) project - deploy via Docker image or static files | - | No | +| `--source-type ` | Manual deployment method: manual (flexible), docker_image, or static_files | - | Yes | +| `--image ` | Docker image for the first deployment (manual mode) | - | Yes | +| `--port ` | Application/container port (manual mode, default: 3000) | - | Yes | +| `-y, --yes` | Skip optional prompts (services, env vars, set-default) | - | No | ### `projects show` (alias: `get`) @@ -200,6 +202,7 @@ Update git repository settings | `--branch ` | Main branch | - | Yes | | `--directory ` | App directory path | - | Yes | | `--preset ` | Build preset (auto, nextjs, nodejs, static, docker, rust, go, python) | - | Yes | +| `--connection ` | Git connection ID (links the project to an actual clone-access connection; omit to leave the existing connection unchanged) | - | Yes | | `--json` | Output in JSON format | - | No | | `-y, --yes` | Skip prompts, use provided/existing values (for automation) | - | No | @@ -234,7 +237,7 @@ Delete a project ## `deploy` -Deploy a project +Deploy a project from git **Options:** @@ -244,8 +247,68 @@ Deploy a project | `-e, --environment ` | Target environment name | - | Yes | | `--environment-id ` | Target environment ID | - | Yes | | `-b, --branch ` | Git branch to deploy | - | Yes | +| `-c, --commit ` | Specific commit SHA to deploy | - | Yes | +| `--no-wait` | Do not wait for deployment to complete | - | No | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +## `deploy:static` (alias: `deploy-static`) + +Deploy static files (tar.gz, zip, or directory) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--path ` | Path to static files archive or directory | - | Yes | +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Target environment name | `production` | Yes | +| `--environment-id ` | Target environment ID | - | Yes | +| `--no-wait` | Do not wait for deployment to complete | - | No | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--metadata ` | Additional metadata (JSON format) | - | Yes | +| `--health-check-path ` | HTTP health-check path (must start with "/", e.g. /api/healthz). Overrides .temps.yaml; also updates the uptime monitor. | - | Yes | +| `--timeout ` | Timeout in seconds for --wait | `300` | Yes | + +## `deploy:image` (alias: `deploy-image`) + +Deploy a pre-built Docker image + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--image ` | Docker image reference (e.g., ghcr.io/org/app:v1.0) | - | Yes | +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Target environment name | `production` | Yes | +| `--environment-id ` | Target environment ID | - | Yes | +| `--no-wait` | Do not wait for deployment to complete | - | No | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--metadata ` | Additional metadata (JSON format) | - | Yes | +| `--health-check-path ` | HTTP health-check path (must start with "/", e.g. /api/healthz). Overrides .temps.yaml; also updates the uptime monitor. | - | Yes | +| `--timeout ` | Timeout in seconds for --wait | `300` | Yes | + +## `deploy:local-image` (alias: `deploy-local-image`) + +Build and deploy a local Docker image (or deploy existing image with --image) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--image ` | Use existing local image instead of building (skips build) | - | Yes | +| `-f, --dockerfile ` | Path to Dockerfile | `Dockerfile` | Yes | +| `-c, --context ` | Build context directory | `.` | Yes | +| `--build-arg ` | Build arguments (can be specified multiple times) | - | Yes | +| `--no-build` | Skip building, requires --image | - | No | +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Target environment name | `production` | Yes | +| `--environment-id ` | Target environment ID | - | Yes | +| `-t, --tag ` | Tag for the built/uploaded image | - | Yes | | `--no-wait` | Do not wait for deployment to complete | - | No | | `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--metadata ` | Additional metadata (JSON format) | - | Yes | +| `--health-check-path ` | HTTP health-check path (must start with "/", e.g. /api/healthz). Overrides .temps.yaml; also updates the uptime monitor. | - | Yes | +| `--timeout ` | Timeout in seconds for --wait | `600` | Yes | ## `deployments` (alias: `deploys`) @@ -260,6 +323,7 @@ Manage deployments - `pause` - Pause a deployment - `resume` - Resume a paused deployment - `teardown` - Teardown a deployment and remove all resources +- `logs` - Show deployment build logs ### `deployments list` (alias: `ls`) @@ -270,8 +334,11 @@ List deployments | Flag | Description | Default | Required | |------|-------------|---------|----------| | `-p, --project ` | Project slug or ID | - | Yes | -| `-e, --environment ` | Filter by environment | - | Yes | +| `-e, --environment ` | Filter by environment name (client-side) | - | Yes | +| `--environment-id ` | Filter by environment ID (server-side) | - | Yes | | `-n, --limit ` | Limit results | `10` | Yes | +| `--page ` | Page number | - | Yes | +| `--per-page ` | Items per page | - | Yes | | `--json` | Output in JSON format | - | No | ### `deployments status` @@ -344,9 +411,9 @@ Teardown a deployment and remove all resources | `-d, --deployment-id ` | Deployment ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | -## `logs` +### `deployments logs` -Stream deployment logs +Show deployment build logs **Options:** @@ -370,6 +437,9 @@ Manage custom domains - `remove` (`rm`) - Remove a domain - `ssl` - Manage SSL certificate - `status` - Check domain status +- `orders` (`order`) - Manage ACME orders for SSL certificate provisioning +- `dns-challenge` - Setup DNS challenge records automatically using a DNS provider +- `http-debug` - Debug HTTP-01 challenge for a domain ### `domains list` (alias: `ls`) @@ -389,12 +459,20 @@ Add a custom domain | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-d, --domain ` | Domain name | - | Yes | | `-c, --challenge ` | Challenge type (http-01 or dns-01) | `http-01` | Yes | +| `-y, --yes` | Skip confirmation prompts | - | No | ### `domains verify` Verify domain and provision SSL certificate +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-d, --domain ` | Domain name | - | Yes | + ### `domains remove` (alias: `rm`) Remove a domain @@ -403,7 +481,9 @@ Remove a domain | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-d, --domain ` | Domain name | - | Yes | | `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | ### `domains ssl` @@ -413,12 +493,106 @@ Manage SSL certificate | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-d, --domain ` | Domain name | - | Yes | | `--renew` | Force certificate renewal | - | No | ### `domains status` Check domain status +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-d, --domain ` | Domain name | - | Yes | + +### `domains orders` (alias: `order`) + +Manage ACME orders for SSL certificate provisioning + +**Subcommands:** + +- `list` (`ls`) - List all ACME orders +- `show` - Show ACME order for a domain +- `create` - Create or recreate an ACME order for a domain +- `finalize` - Finalize an ACME order (complete challenge validation) +- `cancel` - Cancel an ACME order for a domain + +#### `domains orders list` (alias: `ls`) + +List all ACME orders + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +#### `domains orders show` + +Show ACME order for a domain + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `domains orders create` + +Create or recreate an ACME order for a domain + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | + +#### `domains orders finalize` + +Finalize an ACME order (complete challenge validation) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | + +#### `domains orders cancel` + +Cancel an ACME order for a domain + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `domains dns-challenge` + +Setup DNS challenge records automatically using a DNS provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | +| `--provider-id ` | DNS provider ID | - | Yes | + +### `domains http-debug` + +Debug HTTP-01 challenge for a domain + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-d, --domain ` | Domain name | - | Yes | +| `--json` | Output in JSON format | - | No | + ## `environments` (alias: `envs`, `env`) Manage environments and environment variables @@ -430,7 +604,9 @@ Manage environments and environment variables - `delete` (`rm`) - Delete an environment - `vars` - Manage environment variables - `resources` - View or set CPU/memory resources for an environment +- `force-https` - View or set the HTTP to HTTPS redirect override for an environment - `scale` - View or set the number of replicas for an environment +- `crons` - Manage cron jobs ### `environments list` (alias: `ls`) @@ -440,6 +616,7 @@ List environments for a project | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | | `--json` | Output in JSON format | - | No | ### `environments create` @@ -450,6 +627,7 @@ Create a new environment | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | | `-n, --name ` | Environment name | - | Yes | | `-b, --branch ` | Git branch | - | Yes | | `--preview` | Set as preview environment | - | No | @@ -462,12 +640,19 @@ Delete an environment | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | ### `environments vars` Manage environment variables +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | + **Subcommands:** - `list` (`ls`) - List environment variables @@ -510,6 +695,7 @@ Set an environment variable | `-e, --environments ` | Comma-separated environment names (interactive if not provided) | - | Yes | | `--no-preview` | Exclude from preview environments | - | No | | `--update` | Update existing variable instead of creating new | - | No | +| `--secret` | Store as a secret: the value is masked in the UI and never returned by the API. One-way — a secret cannot later be made non-secret | - | No | #### `environments vars delete` (alias: `rm`, `unset`) @@ -552,12 +738,27 @@ View or set CPU/memory resources for an environment | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | | `--cpu ` | CPU limit in millicores (e.g., 500 = 0.5 CPU) | - | Yes | | `--memory ` | Memory limit in MB (e.g., 512) | - | Yes | | `--cpu-request ` | CPU request in millicores (guaranteed minimum) | - | Yes | | `--memory-request ` | Memory request in MB (guaranteed minimum) | - | Yes | | `--json` | Output in JSON format | - | No | +### `environments force-https` + +View or set the HTTP to HTTPS redirect override for an environment + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `--enable` | Always redirect plain HTTP to HTTPS, even without a local certificate | - | No | +| `--disable` | Never redirect: keep serving this environment over plain HTTP | - | No | +| `--inherit` | Clear the override and follow the proxy default | - | No | +| `--json` | Output in JSON format | - | No | + ### `environments scale` View or set the number of replicas for an environment @@ -566,23 +767,31 @@ View or set the number of replicas for an environment | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | `production` | Yes | +| `-r, --replicas ` | Number of replicas to set | - | Yes | | `--json` | Output in JSON format | - | No | -## `providers` (alias: `provider`) +### `environments crons` -Manage Git providers +Manage cron jobs + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | **Subcommands:** -- `list` (`ls`) - List configured Git providers -- `add` - Add a new Git provider (interactive) -- `remove` (`rm`) - Remove a Git provider -- `show` - Show Git provider details -- `git` - Manage Git providers +- `list` (`ls`) - List cron jobs for an environment +- `show` - Show cron job details +- `executions` (`execs`) - Show cron job execution history -### `providers list` (alias: `ls`) +#### `environments crons list` (alias: `ls`) -List configured Git providers +List cron jobs for an environment **Options:** @@ -590,46 +799,50 @@ List configured Git providers |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | -### `providers add` - -Add a new Git provider (interactive) - -### `providers remove` (alias: `rm`) +#### `environments crons show` -Remove a Git provider +Show cron job details **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-f, --force` | Skip confirmation | - | No | +| `--id ` | Cron job ID | - | Yes | +| `--json` | Output in JSON format | - | No | -### `providers show` +#### `environments crons executions` (alias: `execs`) -Show Git provider details +Show cron job execution history **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Cron job ID | - | Yes | +| `--page ` | Page number | `1` | Yes | +| `--per-page ` | Items per page | `20` | Yes | | `--json` | Output in JSON format | - | No | -### `providers git` +## `providers` (alias: `provider`) Manage Git providers **Subcommands:** -- `connect` - Connect a Git provider (github, gitlab) -- `repos` - List available repositories - -#### `providers git connect` - -Connect a Git provider (github, gitlab) +- `list` (`ls`) - List configured Git providers +- `add` - Add a new Git provider +- `remove` (`rm`) - Remove a Git provider +- `show` - Show Git provider details +- `activate` - Activate a Git provider +- `deactivate` - Deactivate a Git provider +- `safe-delete` - Safely delete a Git provider (checks dependencies first) +- `deletion-check` - Check if a Git provider can be safely deleted +- `git` - Manage Git providers +- `connections` (`conn`) - Manage Git provider connections -#### `providers git repos` +### `providers list` (alias: `ls`) -List available repositories +List configured Git providers **Options:** @@ -637,82 +850,449 @@ List available repositories |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | -## `backups` (alias: `backup`) +### `providers add` -Manage backup schedules and backups +Add a new Git provider -**Subcommands:** +**Options:** -- `schedules` (`schedule`) - Manage backup schedules -- `list` (`ls`) - List backups for a schedule -- `show` - Show backup details +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --provider ` | Provider type (github, gitlab, bitbucket, gitea, generic) | - | Yes | +| `-n, --name ` | Provider name | - | Yes | +| `-t, --token ` | Personal access token (or Bitbucket access token / app password) | - | Yes | +| `--base-url ` | Instance base URL (GitLab/Gitea self-hosted; required for gitea) | - | Yes | +| `--username ` | Bitbucket username (selects app-password auth) | - | Yes | +| `--password ` | Bitbucket app password (used with --username) | - | Yes | +| `--clone-url ` | HTTPS clone URL (generic provider) | - | Yes | +| `--token-username ` | HTTP Basic username for the token (generic; default x-access-token) | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | -### `backups schedules` (alias: `schedule`) +### `providers remove` (alias: `rm`) -Manage backup schedules +Remove a Git provider -**Subcommands:** +**Options:** -- `list` (`ls`) - List backup schedules -- `create` - Create a backup schedule -- `show` - Show backup schedule details -- `enable` - Enable a backup schedule -- `disable` - Disable a backup schedule -- `delete` (`rm`) - Delete a backup schedule +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | -#### `backups schedules list` (alias: `ls`) +### `providers show` -List backup schedules +Show Git provider details **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | | `--json` | Output in JSON format | - | No | -#### `backups schedules create` - -Create a backup schedule - -#### `backups schedules show` +### `providers activate` -Show backup schedule details +Activate a Git provider **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output in JSON format | - | No | +| `--id ` | Provider ID | - | Yes | -#### `backups schedules enable` +### `providers deactivate` -Enable a backup schedule +Deactivate a Git provider -#### `backups schedules disable` +**Options:** -Disable a backup schedule +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | -#### `backups schedules delete` (alias: `rm`) +### `providers safe-delete` -Delete a backup schedule +Safely delete a Git provider (checks dependencies first) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | -### `backups list` (alias: `ls`) +### `providers deletion-check` -List backups for a schedule +Check if a Git provider can be safely deleted **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | | `--json` | Output in JSON format | - | No | -### `backups show` +### `providers git` + +Manage Git providers + +**Subcommands:** + +- `connect` - Connect a Git provider (github, gitlab, bitbucket, gitea, generic) +- `repos` - List available repositories + +#### `providers git connect` + +Connect a Git provider (github, gitlab, bitbucket, gitea, generic) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --provider ` | Provider type (github, gitlab, bitbucket, gitea, generic) | - | Yes | +| `-n, --name ` | Provider name | - | Yes | +| `-t, --token ` | Personal access token (or Bitbucket access token / app password) | - | Yes | +| `--base-url ` | Instance base URL (GitLab/Gitea self-hosted; required for gitea) | - | Yes | +| `--username ` | Bitbucket username (selects app-password auth) | - | Yes | +| `--password ` | Bitbucket app password (used with --username) | - | Yes | +| `--clone-url ` | HTTPS clone URL (generic provider) | - | Yes | +| `--token-username ` | HTTP Basic username for the token (generic; default x-access-token) | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +#### `providers git repos` + +List available repositories + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID (optional, lists all if not provided) | - | Yes | +| `--json` | Output in JSON format | - | No | +| `--search ` | Search repositories by name | - | Yes | +| `--page ` | Page number | - | Yes | +| `--per-page ` | Items per page (max: 100) | - | Yes | +| `--sort ` | Sort by field (name, created_at, updated_at, stars) | - | Yes | +| `--direction ` | Sort direction: asc or desc | - | Yes | +| `--language ` | Filter by programming language | - | Yes | +| `--owner ` | Filter by repository owner | - | Yes | + +### `providers connections` (alias: `conn`) + +Manage Git provider connections + +**Subcommands:** + +- `list` (`ls`) - List all Git connections +- `show` - Show connection details for a provider +- `delete` (`rm`) - Delete a Git connection +- `activate` - Activate a Git connection +- `deactivate` - Deactivate a Git connection +- `sync` - Sync repositories for a Git connection +- `update-token` - Update access token for a Git connection +- `validate` - Validate a Git connection + +#### `providers connections list` (alias: `ls`) + +List all Git connections + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | +| `--page ` | Page number | - | Yes | +| `--per-page ` | Items per page (default: 30, max: 100) | - | Yes | +| `--sort ` | Sort by field (created_at, updated_at, account_name) | - | Yes | +| `--direction ` | Sort direction: asc or desc (default: desc) | - | Yes | + +#### `providers connections show` + +Show connection details for a provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `providers connections delete` (alias: `rm`) + +Delete a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +#### `providers connections activate` + +Activate a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | + +#### `providers connections deactivate` + +Deactivate a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | + +#### `providers connections sync` + +Sync repositories for a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | + +#### `providers connections update-token` + +Update access token for a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | +| `-t, --token ` | New access token | - | Yes | + +#### `providers connections validate` + +Validate a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +## `backups` (alias: `backup`) + +Manage backup schedules and backups + +**Subcommands:** + +- `schedules` (`schedule`) - Manage backup schedules +- `sources` (`source`) - Manage S3 backup sources +- `list` (`ls`) - List backups for a schedule +- `show` - Show backup details +- `delete` (`rm`) - Permanently delete one terminal backup +- `cleanup` - Delete backups expired by their schedule retention policy +- `run-service` - Run a backup for an external service + +### `backups schedules` (alias: `schedule`) + +Manage backup schedules + +**Subcommands:** + +- `list` (`ls`) - List backup schedules +- `create` - Create a backup schedule +- `show` - Show backup schedule details +- `enable` - Enable a backup schedule +- `disable` - Disable a backup schedule +- `delete` (`rm`) - Delete a backup schedule + +#### `backups schedules list` (alias: `ls`) + +List backup schedules + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +#### `backups schedules create` + +Create a backup schedule + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-n, --name ` | Schedule name | - | Yes | +| `-t, --type ` | Backup type (full, incremental) | - | Yes | +| `-s, --schedule ` | Schedule expression (cron format) | - | Yes | +| `-r, --retention ` | Retention period in days | - | Yes | +| `-d, --description ` | Description | - | Yes | +| `--s3-source-id ` | S3 Source ID | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +#### `backups schedules show` + +Show backup schedule details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Schedule ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `backups schedules enable` + +Enable a backup schedule + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Schedule ID | - | Yes | + +#### `backups schedules disable` + +Disable a backup schedule + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Schedule ID | - | Yes | + +#### `backups schedules delete` (alias: `rm`) + +Delete a backup schedule + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Schedule ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `backups sources` (alias: `source`) + +Manage S3 backup sources + +**Subcommands:** + +- `list` (`ls`) - List S3 sources +- `create` - Create an S3 source +- `show` - Show S3 source details +- `update` - Update an S3 source +- `remove` (`rm`) - Delete an S3 source +- `backups` - List backups for an S3 source +- `run` - Trigger a backup for an S3 source + +#### `backups sources list` (alias: `ls`) + +List S3 sources + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +#### `backups sources create` + +Create an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-n, --name ` | Source name | - | Yes | +| `--bucket ` | S3 bucket name | - | Yes | +| `--region ` | S3 region | - | Yes | +| `--endpoint ` | S3 endpoint (for S3-compatible services) | - | Yes | +| `--access-key ` | Access key ID | - | Yes | +| `--secret-key ` | Secret access key | - | Yes | +| `--prefix ` | Bucket path/prefix | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +#### `backups sources show` + +Show S3 source details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `backups sources update` + +Update an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | +| `-n, --name ` | New source name | - | Yes | +| `--bucket ` | New S3 bucket name | - | Yes | +| `--region ` | New S3 region | - | Yes | +| `--endpoint ` | New S3 endpoint | - | Yes | +| `--access-key ` | New access key ID | - | Yes | +| `--secret-key ` | New secret access key | - | Yes | +| `--prefix ` | New bucket path/prefix | - | Yes | + +#### `backups sources remove` (alias: `rm`) + +Delete an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +#### `backups sources backups` + +List backups for an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `backups sources run` + +Trigger a backup for an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | + +### `backups list` (alias: `ls`) + +List backups for a schedule + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--schedule-id ` | Schedule ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `backups show` Show backup details @@ -720,11 +1300,49 @@ Show backup details | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output in JSON format | - | No | +| `--id ` | Backup ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `backups delete` (alias: `rm`) + +Permanently delete one terminal backup + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Backup UUID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `backups cleanup` + +Delete backups expired by their schedule retention policy + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--dry-run` | Preview expired backups without deleting them | - | No | +| `--schedule-id ` | Limit cleanup to one schedule | - | Yes | +| `-y, --yes` | Skip confirmation prompt | - | No | +| `--json` | Output the cleanup report as JSON | - | No | + +### `backups run-service` + +Run a backup for an external service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | External service ID | - | Yes | +| `--s3-source-id ` | S3 source ID to store the backup | - | Yes | +| `-t, --type ` | Backup type (e.g., full, incremental) | - | Yes | ## `runtime-logs` (alias: `rlogs`) -Stream runtime container logs (not build logs) +View runtime container logs (use -f to follow in real-time) **Options:** @@ -735,15 +1353,19 @@ Stream runtime container logs (not build logs) | `-c, --container ` | Container ID (partial match supported) | - | Yes | | `-n, --tail ` | Number of lines to tail | `1000` | Yes | | `-t, --timestamps` | Show timestamps | - | No | +| `-f, --follow` | Follow log output (stream in real-time) | - | No | ## `notifications` (alias: `notify`) -Manage notification providers (Slack, Email, etc.) +Manage notification providers (Slack, Email, Webhook, etc.) **Subcommands:** - `list` (`ls`) - List configured notification providers -- `add` - Add a new notification provider (interactive) +- `add` - Add a new notification provider +- `update` - Update a notification provider +- `enable` - Enable a notification provider +- `disable` - Disable a notification provider - `show` - Show notification provider details - `remove` (`rm`) - Remove a notification provider - `test` - Send a test notification @@ -756,172 +1378,539 @@ List configured notification providers | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output in JSON format | - | No | - -### `notifications add` - -Add a new notification provider (interactive) +| `--json` | Output in JSON format | - | No | + +### `notifications add` + +Add a new notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-t, --type ` | Provider type (slack, email, webhook) | - | Yes | +| `-n, --name ` | Provider name | - | Yes | +| `-w, --webhook-url ` | Webhook URL (for slack) | - | Yes | +| `-c, --channel ` | Channel name (for slack, optional) | - | Yes | +| `--smtp-host ` | SMTP host (for email) | - | Yes | +| `--smtp-port ` | SMTP port (for email) | - | Yes | +| `--username ` | SMTP username (for email) | - | Yes | +| `--password ` | SMTP password (for email) | - | Yes | +| `--from-address
` | From email address (for email) | - | Yes | +| `--from-name ` | From display name (for email, optional) | - | Yes | +| `--to-addresses ` | Comma-separated recipient addresses (for email) | - | Yes | +| `--url ` | Webhook URL (for webhook) | - | Yes | +| `--method ` | HTTP method: POST, PUT, PATCH (for webhook, default: POST) | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +### `notifications update` + +Update a notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `-n, --name ` | New provider name | - | Yes | +| `--enabled ` | Enable or disable (true/false) | - | Yes | +| `-w, --webhook-url ` | Webhook URL (for slack) | - | Yes | +| `-c, --channel ` | Channel name (for slack) | - | Yes | +| `--smtp-host ` | SMTP host (for email) | - | Yes | +| `--smtp-port ` | SMTP port (for email) | - | Yes | +| `--username ` | SMTP username (for email) | - | Yes | +| `--password ` | SMTP password (for email) | - | Yes | +| `--from-address
` | From email address (for email) | - | Yes | +| `--from-name ` | From display name (for email) | - | Yes | +| `--to-addresses ` | Comma-separated recipient addresses (for email) | - | Yes | +| `--url ` | Webhook URL (for webhook) | - | Yes | +| `--method ` | HTTP method: POST, PUT, PATCH (for webhook) | - | Yes | +| `--json` | Output in JSON format | - | No | +| `-y, --yes` | Skip confirmation prompts | - | No | + +### `notifications enable` + +Enable a notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `notifications disable` + +Disable a notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `notifications show` + +Show notification provider details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `notifications remove` (alias: `rm`) + +Remove a notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `notifications test` + +Send a test notification + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | + +## `dns` + +Manage DNS providers for automated domain verification + +**Subcommands:** + +- `list` (`ls`) - List configured DNS providers +- `add` - Add a new DNS provider +- `show` - Show DNS provider details +- `remove` (`rm`) - Remove a DNS provider +- `test` - Test DNS provider connection +- `zones` - List available zones in a DNS provider + +### `dns list` (alias: `ls`) + +List configured DNS providers + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +### `dns add` + +Add a new DNS provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-t, --type ` | Provider type (cloudflare, route53, digitalocean, namecheap, gcp, azure, manual) | - | Yes | +| `-n, --name ` | Provider name | - | Yes | +| `-d, --description ` | Provider description | - | Yes | +| `--api-token ` | Cloudflare API token | - | Yes | +| `--account-id ` | Cloudflare account ID (optional) | - | Yes | +| `--access-key-id ` | AWS access key ID | - | Yes | +| `--secret-access-key ` | AWS secret access key | - | Yes | +| `--region ` | AWS region | - | Yes | +| `--api-user ` | Namecheap API user | - | Yes | +| `--api-key ` | Namecheap API key | - | Yes | +| `--username ` | Namecheap username | - | Yes | +| `--client-ip ` | Namecheap whitelisted client IP | - | Yes | +| `--project-id ` | GCP project ID | - | Yes | +| `--service-account-email ` | GCP service account email | - | Yes | +| `--private-key-id ` | GCP private key ID | - | Yes | +| `--private-key ` | GCP private key | - | Yes | +| `--tenant-id ` | Azure tenant ID | - | Yes | +| `--client-id ` | Azure client ID | - | Yes | +| `--client-secret ` | Azure client secret | - | Yes | +| `--subscription-id ` | Azure subscription ID | - | Yes | +| `--resource-group ` | Azure resource group | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +### `dns show` + +Show DNS provider details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `dns remove` (alias: `rm`) + +Remove a DNS provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation (alias for --force) | - | No | + +### `dns test` + +Test DNS provider connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | + +### `dns zones` + +List available zones in a DNS provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +## `services` (alias: `svc`) + +Manage external services (databases, caches, storage) + +**Subcommands:** + +- `list` (`ls`) - List all external services +- `create` (`add`) - Create a new external service +- `show` - Show service details +- `remove` (`rm`) - Remove a service +- `start` - Start a stopped service +- `stop` - Stop a running service +- `types` - List available service types +- `projects` - List projects linked to a service +- `update` - Update a service +- `upgrade` - Upgrade a service to a newer version +- `import` - Import an existing external service +- `link` - Link a service to a project +- `unlink` - Unlink a service from a project +- `connect` - Get connection info for a service by name or slug +- `env` - Show environment variables for a linked service +- `env-var` - Get a specific environment variable +- `logs` - View persisted logs for an external service +- `slow-queries` - Show slowest PostgreSQL queries from pg_stat_statements +- `enable-pg-stat-statements` - Enable pg_stat_statements on a standalone Postgres service by restarting its container (drops active connections briefly) +- `restore-capabilities` - Show what restore modes a service supports (in-place / new service / PITR) +- `list-backups` - List backups stored on an S3 source +- `restore` - Restore a service from a backup (in-place, new service, or PITR) +- `restore-runs` - List recent restore runs for a service +- `restore-run` - Show a single restore run + +### `services list` (alias: `ls`) + +List all external services + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +### `services create` (alias: `add`) + +Create a new external service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-t, --type ` | Service type (postgres, mongodb, redis, s3) | - | Yes | +| `-n, --name ` | Service name | - | Yes | +| `-s, --set ` | Set a parameter (repeatable) | `` | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +### `services show` + +Show service details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `services remove` (alias: `rm`) + +Remove a service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `services start` + +Start a stopped service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | + +### `services stop` + +Stop a running service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | + +### `services types` + +List available service types + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +**Subcommands:** + +- `info` - Show parameters schema for a service type (useful for automation) + +#### `services types info` + +Show parameters schema for a service type (useful for automation) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output as raw JSON schema (default) | - | No | + +### `services projects` + +List projects linked to a service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `services update` + +Update a service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-n, --name ` | Docker image name (e.g., postgres:18-alpine) | - | Yes | +| `-s, --set ` | Set a parameter (repeatable) | `` | Yes | + +### `services upgrade` + +Upgrade a service to a newer version + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-v, --version ` | Docker image to upgrade to (e.g., postgres:18-alpine) | - | Yes | + +### `services import` + +Import an existing external service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-t, --type ` | Service type (postgres, mongodb, redis, s3) | - | Yes | +| `-n, --name ` | Service name | - | Yes | +| `--container-id ` | Container ID or name to import | - | Yes | +| `-s, --set ` | Set a parameter (repeatable) | `` | Yes | +| `--version ` | Optional version override | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | -### `notifications show` +### `services link` -Show notification provider details +Link a service to a project **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output in JSON format | - | No | +| `--id ` | Service ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | -### `notifications remove` (alias: `rm`) +### `services unlink` -Remove a notification provider +Unlink a service from a project **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | | `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | -### `notifications test` - -Send a test notification - -## `dns` (alias: `dns-providers`) +### `services connect` -Manage DNS providers for automated domain verification +Get connection info for a service by name or slug -**Subcommands:** +**Options:** -- `list` (`ls`) - List configured DNS providers -- `add` - Add a new DNS provider (interactive) -- `show` - Show DNS provider details -- `remove` (`rm`) - Remove a DNS provider -- `test` - Test DNS provider connection -- `zones` - List available zones in a DNS provider +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | +| `--json` | Output in JSON format | - | No | -### `dns list` (alias: `ls`) +### `services env` -List configured DNS providers +Show environment variables for a linked service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | | `--json` | Output in JSON format | - | No | -### `dns add` - -Add a new DNS provider (interactive) - -### `dns show` +### `services env-var` -Show DNS provider details +Get a specific environment variable **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | +| `--var ` | Environment variable name | - | Yes | | `--json` | Output in JSON format | - | No | -### `dns remove` (alias: `rm`) +### `services logs` -Remove a DNS provider +View persisted logs for an external service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-f, --force` | Skip confirmation | - | No | - -### `dns test` - -Test DNS provider connection +| `--id ` | Service ID | - | Yes | +| `--from ` | Start of time range. ISO 8601 timestamp or a relative duration like "1h", "24h", "7d" (default: 24h ago) | - | Yes | +| `--to ` | End of time range. ISO 8601 timestamp (default: now) | - | Yes | +| `-l, --level ` | Comma-separated log levels to include: ERROR,WARN,INFO,DEBUG,TRACE | - | Yes | +| `-n, --tail ` | Maximum number of log lines to fetch (default: 200, max: 1000) | `200` | Yes | +| `-t, --text ` | Filter log lines by text (case-insensitive) | - | Yes | +| `--json` | Output raw JSON instead of formatted lines | - | No | -### `dns zones` +### `services slow-queries` -List available zones in a DNS provider +Show slowest PostgreSQL queries from pg_stat_statements **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output in JSON format | - | No | +| `--id ` | Service ID | - | Yes | +| `--page ` | Page number (1-based, default: 1) | `1` | Yes | +| `--page-size ` | Rows per page (1–100, default: 20) | `20` | Yes | +| `--sort-by ` | Sort column: calls, total_exec_time_ms, mean_exec_time_ms, rows, cache_hit_ratio (default: mean_exec_time_ms) | - | Yes | +| `--sort-order ` | Sort direction: asc or desc (default: desc) | - | Yes | +| `--json` | Output raw JSON instead of a formatted table | - | No | -## `services` (alias: `svc`) +### `services enable-pg-stat-statements` -Manage external services (databases, caches, storage) +Enable pg_stat_statements on a standalone Postgres service by restarting its container (drops active connections briefly) -**Subcommands:** +**Options:** -- `list` (`ls`) - List all external services -- `create` (`add`) - Create a new external service (interactive) -- `show` - Show service details -- `remove` (`rm`) - Remove a service -- `start` - Start a stopped service -- `stop` - Stop a running service -- `types` - List available service types -- `projects` - List projects linked to a service +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-y, --yes` | Skip the restart confirmation prompt (for automation) | - | No | -### `services list` (alias: `ls`) +### `services restore-capabilities` -List all external services +Show what restore modes a service supports (in-place / new service / PITR) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | | `--json` | Output in JSON format | - | No | -### `services create` (alias: `add`) - -Create a new external service (interactive) +### `services list-backups` -### `services show` - -Show service details +List backups stored on an S3 source **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--s3-source-id ` | S3 source ID | - | Yes | | `--json` | Output in JSON format | - | No | -### `services remove` (alias: `rm`) +### `services restore` -Remove a service +Restore a service from a backup (in-place, new service, or PITR) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-f, --force` | Skip confirmation | - | No | - -### `services start` - -Start a stopped service - -### `services stop` - -Stop a running service +| `--id ` | Source service ID (the service the backup came from) | - | Yes | +| `--backup-id ` | Backup ID to restore from (see `list-backups`) | - | Yes | +| `--new-service [name]` | Clone into a new service. Omit the value or pass "auto" to accept the auto-suggested name. | - | No | +| `--pitr ` | Point-in-time recovery target, ISO 8601 timestamp (requires WAL-G backup). Combine with --new-service to route PITR into a new service. | - | Yes | +| `-y, --yes` | Skip confirmation | - | No | +| `--no-wait` | Return immediately without polling run status | - | No | +| `--json` | Output in JSON format | - | No | -### `services types` +### `services restore-runs` -List available service types +List recent restore runs for a service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | | `--json` | Output in JSON format | - | No | -### `services projects` +### `services restore-run` -List projects linked to a service +Show a single restore run **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Restore run ID | - | Yes | | `--json` | Output in JSON format | - | No | ## `settings` @@ -931,7 +1920,7 @@ Manage platform settings **Subcommands:** - `show` (`get`) - Show current platform settings -- `update` (`set`) - Update platform settings (interactive) +- `update` (`set`) - Update platform settings - `set-external-url` - Set the external URL for the platform - `set-preview-domain` - Set the preview domain pattern @@ -947,16 +1936,43 @@ Show current platform settings ### `settings update` (alias: `set`) -Update platform settings (interactive) +Update platform settings + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-s, --setting ` | Setting to update (external_url, preview_domain, letsencrypt, rate_limiting, security_headers, screenshots) | - | Yes | +| `-v, --value ` | Value for the setting | - | Yes | +| `--external-url ` | External URL for the platform | - | Yes | +| `--preview-domain ` | Preview domain pattern | - | Yes | +| `--letsencrypt-email ` | Let's Encrypt email | - | Yes | +| `--letsencrypt-mode ` | Let's Encrypt mode (staging, production) | - | Yes | +| `--rate-limiting-enabled ` | Enable rate limiting (true/false) | - | Yes | +| `--rate-limiting-rpm ` | Requests per minute | - | Yes | +| `--screenshots-enabled ` | Enable screenshots (true/false) | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | ### `settings set-external-url` Set the external URL for the platform +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--url ` | External URL | - | Yes | + ### `settings set-preview-domain` Set the preview domain pattern +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain ` | Preview domain pattern | - | Yes | + ## `users` Manage platform users @@ -984,6 +2000,16 @@ List all users Create a new user +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-u, --username ` | Username | - | Yes | +| `-e, --email ` | Email address | - | Yes | +| `-p, --password ` | Password (if not provided, invite email will be sent) | - | Yes | +| `-r, --roles ` | Comma-separated roles (admin, developer, viewer) | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + ### `users me` Show current user info @@ -1002,12 +2028,20 @@ Remove a user | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | User ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | ### `users restore` Restore a deleted user +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | User ID | - | Yes | + ### `users role` Manage user roles @@ -1016,6 +2050,7 @@ Manage user roles | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | User ID | - | Yes | | `--add ` | Add a role to user | - | Yes | | `--remove ` | Remove a role from user | - | Yes | @@ -1047,6 +2082,16 @@ List all API keys Create a new API key +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-n, --name ` | API key name | - | Yes | +| `-r, --role ` | Role type (admin, developer, viewer, readonly) | - | Yes | +| `-e, --expires-in ` | Expires in N days (7, 30, 90, 365) | - | Yes | +| `-p, --permissions ` | Comma-separated list of permissions | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + ### `apikeys show` Show API key details @@ -1055,6 +2100,7 @@ Show API key details | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | API key ID | - | Yes | | `--json` | Output in JSON format | - | No | ### `apikeys remove` (alias: `rm`) @@ -1065,16 +2111,30 @@ Delete an API key | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | API key ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | ### `apikeys activate` Activate a deactivated API key +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | API key ID | - | Yes | + ### `apikeys deactivate` Deactivate an API key +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | API key ID | - | Yes | + ### `apikeys permissions` List available API key permissions @@ -1085,7 +2145,7 @@ List available API key permissions |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | -## `monitors` +## `monitors` (alias: `monitoring`) Manage uptime monitors for status pages @@ -1095,7 +2155,7 @@ Manage uptime monitors for status pages - `create` (`add`) - Create a new monitor for a project - `show` - Show monitor details and current status - `remove` (`rm`) - Delete a monitor -- `status` - Get current monitor status +- `status` - Get current status — all monitors for a project, or a single monitor by ID - `history` - Get monitor uptime history ### `monitors list` (alias: `ls`) @@ -1106,12 +2166,25 @@ List all monitors for a project | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | | `--json` | Output in JSON format | - | No | ### `monitors create` (alias: `add`) Create a new monitor for a project +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `-n, --name ` | Monitor name | - | Yes | +| `-t, --type ` | Monitor type (http, tcp, ping) | - | Yes | +| `-i, --interval ` | Check interval in seconds (60, 300, 600, 900, 1800) | - | Yes | +| `--check-path ` | HTTP health-check path (must start with "/", e.g. /api/healthz). Defaults to "/" for HTTP monitors. | - | Yes | +| `--environment-id ` | Environment ID (default: 0 for production) | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + ### `monitors show` Show monitor details and current status @@ -1120,6 +2193,7 @@ Show monitor details and current status | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Monitor ID | - | Yes | | `--json` | Output in JSON format | - | No | ### `monitors remove` (alias: `rm`) @@ -1130,16 +2204,20 @@ Delete a monitor | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Monitor ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | ### `monitors status` -Get current monitor status +Get current status — all monitors for a project, or a single monitor by ID **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Monitor ID (omit to show all monitors for the project) | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json or TEMPS_PROJECT) | - | Yes | | `--json` | Output in JSON format | - | No | ### `monitors history` @@ -1150,6 +2228,7 @@ Get monitor uptime history | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Monitor ID | - | Yes | | `--json` | Output in JSON format | - | No | | `--days ` | Number of days to show | `7` | Yes | @@ -1162,10 +2241,12 @@ Manage webhooks for project events - `list` (`ls`) - List all webhooks for a project - `create` (`add`) - Create a new webhook for a project - `show` - Show webhook details +- `update` - Update a webhook - `remove` (`rm`) - Delete a webhook - `enable` - Enable a webhook - `disable` - Disable a webhook - `events` - List available webhook event types +- `deliveries` - Manage webhook deliveries ### `webhooks list` (alias: `ls`) @@ -1175,12 +2256,23 @@ List all webhooks for a project | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | | `--json` | Output in JSON format | - | No | ### `webhooks create` (alias: `add`) Create a new webhook for a project +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `-u, --url ` | Webhook URL | - | Yes | +| `-e, --events ` | Comma-separated event types (or "all" for all events) | - | Yes | +| `-s, --secret ` | Webhook secret for signature verification | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + ### `webhooks show` Show webhook details @@ -1189,8 +2281,24 @@ Show webhook details | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | | `--json` | Output in JSON format | - | No | +### `webhooks update` + +Update a webhook + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | +| `-u, --url ` | New webhook URL | - | Yes | +| `-e, --events ` | Comma-separated event types (or "all" for all events) | - | Yes | +| `-s, --secret ` | New webhook secret for signature verification | - | Yes | + ### `webhooks remove` (alias: `rm`) Delete a webhook @@ -1199,16 +2307,33 @@ Delete a webhook | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | ### `webhooks enable` Enable a webhook +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | + ### `webhooks disable` Disable a webhook +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | + ### `webhooks events` List available webhook event types @@ -1219,29 +2344,77 @@ List available webhook event types |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | +### `webhooks deliveries` + +Manage webhook deliveries + +**Subcommands:** + +- `list` (`ls`) - List deliveries for a webhook +- `show` - Show delivery details +- `retry` - Retry a failed delivery + +#### `webhooks deliveries list` (alias: `ls`) + +List deliveries for a webhook + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | +| `--limit ` | Number of deliveries to return (default: 50) | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `webhooks deliveries show` + +Show delivery details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | +| `--delivery-id ` | Delivery ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `webhooks deliveries retry` + +Retry a failed delivery + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | +| `--delivery-id ` | Delivery ID | - | Yes | + ## `containers` (alias: `cts`) Manage project containers in environments **Subcommands:** -- `list` (`ls`) - List all containers in an environment +- `list` (`ls`) - List containers in an environment, or across all environments if -e omitted - `show` - Show container details - `start` - Start a stopped container - `stop` - Stop a running container - `restart` - Restart a container -- `metrics` - Get container resource metrics +- `metrics` - Get container resource metrics (all containers if no container ID specified) ### `containers list` (alias: `ls`) -List all containers in an environment +List containers in an environment, or across all environments if -e omitted **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| | `-p, --project-id ` | Project ID | - | Yes | -| `-e, --environment-id ` | Environment ID | - | Yes | +| `-e, --environment-id ` | Environment ID (optional - lists all environments if omitted) | - | Yes | | `--json` | Output in JSON format | - | No | ### `containers show` @@ -1296,7 +2469,7 @@ Restart a container ### `containers metrics` -Get container resource metrics +Get container resource metrics (all containers if no container ID specified) **Options:** @@ -1304,53 +2477,138 @@ Get container resource metrics |------|-------------|---------|----------| | `-p, --project-id ` | Project ID | - | Yes | | `-e, --environment-id ` | Environment ID | - | Yes | -| `-c, --container-id ` | Container ID | - | Yes | +| `-c, --container-id ` | Container ID (optional - shows all if not specified) | - | Yes | | `--json` | Output in JSON format | - | No | +| `-w, --watch` | Watch mode - continuously update metrics | - | No | +| `-i, --interval ` | Refresh interval in seconds (default: 2) | `2` | Yes | +## `flags` (alias: `flag`) ---- +Manage feature flags (runtime config that changes without a redeploy) -## `analytics` (alias: `stats`) +**Subcommands:** -View project analytics from the terminal. +- `list` (`ls`) - List feature flags +- `get` - Show a feature flag and its per-environment values +- `create` - Create a feature flag +- `update` - Update a flag definition (default value, description, visibility) +- `set` - Set a flag value in one environment +- `clear` - Clear a flag override so the environment inherits the default +- `disable` - Kill switch: serve the default in this environment, ignoring any override +- `enable` - Re-enable a flag in this environment after a kill switch +- `archive` - Archive a flag (callers fall back to their own default) -**Subcommands:** +### `flags list` (alias: `ls`) -- `overview` (`o`) - Show analytics dashboard overview -- `top ` - Show breakdown by dimension +List feature flags -### `analytics overview` (alias: `o`) +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Show values for this environment | - | Yes | +| `--include-archived` | Include archived flags | - | No | +| `--page ` | Page number (default: 1) | - | Yes | +| `--page-size ` | Items per page (default: 20, max: 100) | - | Yes | +| `--json` | Output in JSON format | - | No | -Show analytics dashboard overview with key metrics, hourly sparkline, top pages, events, and locations. +### `flags get` -| Flag | Description | Default | -|------|-------------|---------| -| `-p, --project ` | Project slug or ID | - | -| `--period ` | Time period: today, 24h, 7d, 30d, 90d | `24h` | -| `--json` | Output in JSON format | - | +Show a feature flag and its per-environment values -```bash -temps analytics overview -p my-app --period 7d -temps stats -p my-app -``` +**Options:** -### `analytics top ` +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `--json` | Output in JSON format | - | No | -Show breakdown by dimension: `pages`, `referrers`, `browsers`, `os`, `devices`, `countries`, `channels`, `events`, `languages`, `utm_source`, `utm_medium`, `utm_campaign` +### `flags create` -| Flag | Description | Default | -|------|-------------|---------| -| `-p, --project ` | Project slug or ID | - | -| `--period ` | Time period: today, 24h, 7d, 30d, 90d | `24h` | -| `--limit ` | Number of results | `20` | -| `--json` | Output in JSON format | - | +Create a feature flag + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-t, --type ` | Value type: bool, string, number, or json | - | Yes | +| `-d, --default ` | Default value, served when nothing more specific applies | - | Yes | +| `--description ` | What this flag controls | - | Yes | +| `--client-visible` | Allow this flag to be exposed to browsers (default: server-only) | - | No | +| `--json` | Output in JSON format | - | No | + +### `flags update` + +Update a flag definition (default value, description, visibility) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-d, --default ` | New default value | - | Yes | +| `--description ` | New description | - | Yes | +| `--client-visible` | Expose this flag to browsers | - | No | +| `--no-client-visible` | Make this flag server-only | - | No | +| `--json` | Output in JSON format | - | No | + +### `flags set` + +Set a flag value in one environment + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `flags clear` + +Clear a flag override so the environment inherits the default + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | + +### `flags disable` + +Kill switch: serve the default in this environment, ignoring any override + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | + +### `flags enable` + +Re-enable a flag in this environment after a kill switch + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | + +### `flags archive` + +Archive a flag (callers fall back to their own default) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | -```bash -temps analytics top pages -p my-app --period 30d -temps analytics top referrers --period 7d -temps analytics top browsers --json -temps analytics top countries --limit 50 -``` --- @@ -1419,9 +2677,9 @@ The CLI respects the following environment variables: Configuration is stored in: - **Config file**: `~/.temps/config.json` -- **Credentials**: stored securely under `~/.temps/` with restricted permissions (mode 0600), managed by `login`/`logout` +- **Credentials**: Stored securely in `~/.temps/` with restricted file permissions -Use `temps configure show` to view current configuration. +Use `bunx @temps-sdk/cli configure show` to view current configuration. ## Support diff --git a/apps/temps-cli/docs/CLI.mdx b/apps/temps-cli/docs/CLI.mdx index 9c0f33c55..e311b5f80 100644 --- a/apps/temps-cli/docs/CLI.mdx +++ b/apps/temps-cli/docs/CLI.mdx @@ -7,7 +7,7 @@ export const metadata = { > Auto-generated documentation for the Temps CLI. > -> Generated on: 2026-01-03 +> Generated on: 2026-08-03 ## Installation @@ -44,8 +44,9 @@ Manage projects **Subcommands:** +- `secrets` - Manage project secrets — mounted into the deployed container as files at /run/secrets/ (mode 0400), not environment variables. Distinct from `temps secrets` (agent/MCP-sandbox-scoped). - `list` (`ls`) - List all projects -- `create` (`new`) - Create a new project +- `create` (`new`) - Create a new project (git-based or manual deployment) - `show` (`get`) - Show project details - `update` (`edit`) - Update project name and description - `settings` - Update project settings (slug, attack mode, preview environments) @@ -53,6 +54,70 @@ Manage projects - `config` - Update deployment configuration (resources, replicas) - `delete` (`rm`) - Delete a project +### `projects secrets` + +Manage project secrets — mounted into the deployed container as files at /run/secrets/ (mode 0400), not environment variables. Distinct from `temps secrets` (agent/MCP-sandbox-scoped). + +**Subcommands:** + +- `list` (`ls`) - List secrets for a project (values are never returned) +- `create` (`add`) - Create a project secret (mounted at /run/secrets/ on the next deployment) +- `update` - Update a project secret (a redeploy is required for running containers to pick it up) +- `delete` (`rm`) - Delete a project secret + +#### `projects secrets list` (alias: `ls`) + +List secrets for a project (values are never returned) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Filter to one environment | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `projects secrets create` (alias: `add`) + +Create a project secret (mounted at /run/secrets/ on the next deployment) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-k, --key ` | Secret key — becomes the filename at /run/secrets/. Letters, digits, underscore; must start with a letter or underscore. | - | Yes | +| `-v, --value ` | Secret value (<=1 MiB). Prefix with @ to read from a local file, e.g. @./auth.json — never touches shell history. | - | Yes | +| `-e, --environment ` | Scope to one environment (repeatable; default: all) | `` | Yes | +| `--include-in-preview` | Also mount this secret in preview environments | - | No | + +#### `projects secrets update` + +Update a project secret (a redeploy is required for running containers to pick it up) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-k, --key ` | Key of the secret to update | - | Yes | +| `-v, --value ` | New value (<=1 MiB). Prefix with @ to read from a local file. Omit to keep the existing value. | - | Yes | +| `-e, --environment ` | Replace environment scoping (repeatable) | `` | Yes | +| `--include-in-preview` | Include in preview environments | - | No | +| `--no-include-in-preview` | Exclude from preview environments | - | No | + +#### `projects secrets delete` (alias: `rm`) + +Delete a project secret + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation (alias for --force) | - | No | + ### `projects list` (alias: `ls`) List all projects @@ -62,10 +127,12 @@ List all projects | Flag | Description | Default | Required | |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | +| `--page ` | Page number | - | Yes | +| `--per-page ` | Items per page | - | Yes | ### `projects create` (alias: `new`) -Create a new project +Create a new project (git-based or manual deployment) **Options:** @@ -73,7 +140,16 @@ Create a new project |------|-------------|---------|----------| | `-n, --name ` | Project name | - | Yes | | `-d, --description ` | Project description | - | Yes | -| `--repo ` | Git repository URL | - | Yes | +| `--repo ` | Repository in owner/name format (nested groups supported: group/subgroup/name) | - | Yes | +| `--branch ` | Git branch | - | Yes | +| `--directory ` | Root directory (relative to repo) | - | Yes | +| `--preset ` | Build preset (e.g., nextjs, nodejs, static, docker) | - | Yes | +| `--connection ` | Git connection ID | - | Yes | +| `--manual` | Create a manual (non-git) project - deploy via Docker image or static files | - | No | +| `--source-type ` | Manual deployment method: manual (flexible), docker_image, or static_files | - | Yes | +| `--image ` | Docker image for the first deployment (manual mode) | - | Yes | +| `--port ` | Application/container port (manual mode, default: 3000) | - | Yes | +| `-y, --yes` | Skip optional prompts (services, env vars, set-default) | - | No | ### `projects show` (alias: `get`) @@ -131,6 +207,7 @@ Update git repository settings | `--branch ` | Main branch | - | Yes | | `--directory ` | App directory path | - | Yes | | `--preset ` | Build preset (auto, nextjs, nodejs, static, docker, rust, go, python) | - | Yes | +| `--connection ` | Git connection ID (links the project to an actual clone-access connection; omit to leave the existing connection unchanged) | - | Yes | | `--json` | Output in JSON format | - | No | | `-y, --yes` | Skip prompts, use provided/existing values (for automation) | - | No | @@ -165,7 +242,7 @@ Delete a project ## `deploy` -Deploy a project +Deploy a project from git **Options:** @@ -175,8 +252,68 @@ Deploy a project | `-e, --environment ` | Target environment name | - | Yes | | `--environment-id ` | Target environment ID | - | Yes | | `-b, --branch ` | Git branch to deploy | - | Yes | +| `-c, --commit ` | Specific commit SHA to deploy | - | Yes | +| `--no-wait` | Do not wait for deployment to complete | - | No | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +## `deploy:static` (alias: `deploy-static`) + +Deploy static files (tar.gz, zip, or directory) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--path ` | Path to static files archive or directory | - | Yes | +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Target environment name | `production` | Yes | +| `--environment-id ` | Target environment ID | - | Yes | +| `--no-wait` | Do not wait for deployment to complete | - | No | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--metadata ` | Additional metadata (JSON format) | - | Yes | +| `--health-check-path ` | HTTP health-check path (must start with "/", e.g. /api/healthz). Overrides .temps.yaml; also updates the uptime monitor. | - | Yes | +| `--timeout ` | Timeout in seconds for --wait | `300` | Yes | + +## `deploy:image` (alias: `deploy-image`) + +Deploy a pre-built Docker image + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--image ` | Docker image reference (e.g., ghcr.io/org/app:v1.0) | - | Yes | +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Target environment name | `production` | Yes | +| `--environment-id ` | Target environment ID | - | Yes | +| `--no-wait` | Do not wait for deployment to complete | - | No | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--metadata ` | Additional metadata (JSON format) | - | Yes | +| `--health-check-path ` | HTTP health-check path (must start with "/", e.g. /api/healthz). Overrides .temps.yaml; also updates the uptime monitor. | - | Yes | +| `--timeout ` | Timeout in seconds for --wait | `300` | Yes | + +## `deploy:local-image` (alias: `deploy-local-image`) + +Build and deploy a local Docker image (or deploy existing image with --image) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--image ` | Use existing local image instead of building (skips build) | - | Yes | +| `-f, --dockerfile ` | Path to Dockerfile | `Dockerfile` | Yes | +| `-c, --context ` | Build context directory | `.` | Yes | +| `--build-arg ` | Build arguments (can be specified multiple times) | - | Yes | +| `--no-build` | Skip building, requires --image | - | No | +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Target environment name | `production` | Yes | +| `--environment-id ` | Target environment ID | - | Yes | +| `-t, --tag ` | Tag for the built/uploaded image | - | Yes | | `--no-wait` | Do not wait for deployment to complete | - | No | | `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--metadata ` | Additional metadata (JSON format) | - | Yes | +| `--health-check-path ` | HTTP health-check path (must start with "/", e.g. /api/healthz). Overrides .temps.yaml; also updates the uptime monitor. | - | Yes | +| `--timeout ` | Timeout in seconds for --wait | `600` | Yes | ## `deployments` (alias: `deploys`) @@ -191,6 +328,7 @@ Manage deployments - `pause` - Pause a deployment - `resume` - Resume a paused deployment - `teardown` - Teardown a deployment and remove all resources +- `logs` - Show deployment build logs ### `deployments list` (alias: `ls`) @@ -201,8 +339,11 @@ List deployments | Flag | Description | Default | Required | |------|-------------|---------|----------| | `-p, --project ` | Project slug or ID | - | Yes | -| `-e, --environment ` | Filter by environment | - | Yes | +| `-e, --environment ` | Filter by environment name (client-side) | - | Yes | +| `--environment-id ` | Filter by environment ID (server-side) | - | Yes | | `-n, --limit ` | Limit results | `10` | Yes | +| `--page ` | Page number | - | Yes | +| `--per-page ` | Items per page | - | Yes | | `--json` | Output in JSON format | - | No | ### `deployments status` @@ -275,9 +416,9 @@ Teardown a deployment and remove all resources | `-d, --deployment-id ` | Deployment ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | -## `logs` +### `deployments logs` -Stream deployment logs +Show deployment build logs **Options:** @@ -301,6 +442,9 @@ Manage custom domains - `remove` (`rm`) - Remove a domain - `ssl` - Manage SSL certificate - `status` - Check domain status +- `orders` (`order`) - Manage ACME orders for SSL certificate provisioning +- `dns-challenge` - Setup DNS challenge records automatically using a DNS provider +- `http-debug` - Debug HTTP-01 challenge for a domain ### `domains list` (alias: `ls`) @@ -322,6 +466,7 @@ Add a custom domain |------|-------------|---------|----------| | `-d, --domain ` | Domain name | - | Yes | | `-c, --challenge ` | Challenge type (http-01 or dns-01) | `http-01` | Yes | +| `-y, --yes` | Skip confirmation prompts | - | No | ### `domains verify` @@ -366,6 +511,93 @@ Check domain status |------|-------------|---------|----------| | `-d, --domain ` | Domain name | - | Yes | +### `domains orders` (alias: `order`) + +Manage ACME orders for SSL certificate provisioning + +**Subcommands:** + +- `list` (`ls`) - List all ACME orders +- `show` - Show ACME order for a domain +- `create` - Create or recreate an ACME order for a domain +- `finalize` - Finalize an ACME order (complete challenge validation) +- `cancel` - Cancel an ACME order for a domain + +#### `domains orders list` (alias: `ls`) + +List all ACME orders + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +#### `domains orders show` + +Show ACME order for a domain + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `domains orders create` + +Create or recreate an ACME order for a domain + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | + +#### `domains orders finalize` + +Finalize an ACME order (complete challenge validation) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | + +#### `domains orders cancel` + +Cancel an ACME order for a domain + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `domains dns-challenge` + +Setup DNS challenge records automatically using a DNS provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--domain-id ` | Domain ID | - | Yes | +| `--provider-id ` | DNS provider ID | - | Yes | + +### `domains http-debug` + +Debug HTTP-01 challenge for a domain + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-d, --domain ` | Domain name | - | Yes | +| `--json` | Output in JSON format | - | No | + ## `environments` (alias: `envs`, `env`) Manage environments and environment variables @@ -377,7 +609,9 @@ Manage environments and environment variables - `delete` (`rm`) - Delete an environment - `vars` - Manage environment variables - `resources` - View or set CPU/memory resources for an environment +- `force-https` - View or set the HTTP to HTTPS redirect override for an environment - `scale` - View or set the number of replicas for an environment +- `crons` - Manage cron jobs ### `environments list` (alias: `ls`) @@ -387,6 +621,7 @@ List environments for a project | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | | `--json` | Output in JSON format | - | No | ### `environments create` @@ -397,6 +632,7 @@ Create a new environment | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | | `-n, --name ` | Environment name | - | Yes | | `-b, --branch ` | Git branch | - | Yes | | `--preview` | Set as preview environment | - | No | @@ -409,12 +645,19 @@ Delete an environment | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | | `-f, --force` | Skip confirmation | - | No | ### `environments vars` Manage environment variables +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | + **Subcommands:** - `list` (`ls`) - List environment variables @@ -457,6 +700,7 @@ Set an environment variable | `-e, --environments ` | Comma-separated environment names (interactive if not provided) | - | Yes | | `--no-preview` | Exclude from preview environments | - | No | | `--update` | Update existing variable instead of creating new | - | No | +| `--secret` | Store as a secret: the value is masked in the UI and never returned by the API. One-way — a secret cannot later be made non-secret | - | No | #### `environments vars delete` (alias: `rm`, `unset`) @@ -499,12 +743,27 @@ View or set CPU/memory resources for an environment | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | | `--cpu ` | CPU limit in millicores (e.g., 500 = 0.5 CPU) | - | Yes | | `--memory ` | Memory limit in MB (e.g., 512) | - | Yes | | `--cpu-request ` | CPU request in millicores (guaranteed minimum) | - | Yes | | `--memory-request ` | Memory request in MB (guaranteed minimum) | - | Yes | | `--json` | Output in JSON format | - | No | +### `environments force-https` + +View or set the HTTP to HTTPS redirect override for an environment + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `--enable` | Always redirect plain HTTP to HTTPS, even without a local certificate | - | No | +| `--disable` | Never redirect: keep serving this environment over plain HTTP | - | No | +| `--inherit` | Clear the override and follow the proxy default | - | No | +| `--json` | Output in JSON format | - | No | + ### `environments scale` View or set the number of replicas for an environment @@ -513,6 +772,60 @@ View or set the number of replicas for an environment | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | `production` | Yes | +| `-r, --replicas ` | Number of replicas to set | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `environments crons` + +Manage cron jobs + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | + +**Subcommands:** + +- `list` (`ls`) - List cron jobs for an environment +- `show` - Show cron job details +- `executions` (`execs`) - Show cron job execution history + +#### `environments crons list` (alias: `ls`) + +List cron jobs for an environment + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +#### `environments crons show` + +Show cron job details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Cron job ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `environments crons executions` (alias: `execs`) + +Show cron job execution history + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Cron job ID | - | Yes | +| `--page ` | Page number | `1` | Yes | +| `--per-page ` | Items per page | `20` | Yes | | `--json` | Output in JSON format | - | No | ## `providers` (alias: `provider`) @@ -525,7 +838,12 @@ Manage Git providers - `add` - Add a new Git provider - `remove` (`rm`) - Remove a Git provider - `show` - Show Git provider details +- `activate` - Activate a Git provider +- `deactivate` - Deactivate a Git provider +- `safe-delete` - Safely delete a Git provider (checks dependencies first) +- `deletion-check` - Check if a Git provider can be safely deleted - `git` - Manage Git providers +- `connections` (`conn`) - Manage Git provider connections ### `providers list` (alias: `ls`) @@ -545,10 +863,14 @@ Add a new Git provider | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-p, --provider ` | Provider type (github, gitlab) | - | Yes | +| `-p, --provider ` | Provider type (github, gitlab, bitbucket, gitea, generic) | - | Yes | | `-n, --name ` | Provider name | - | Yes | -| `-t, --token ` | Personal access token | - | Yes | -| `--base-url ` | GitLab base URL (for self-hosted GitLab) | - | Yes | +| `-t, --token ` | Personal access token (or Bitbucket access token / app password) | - | Yes | +| `--base-url ` | Instance base URL (GitLab/Gitea self-hosted; required for gitea) | - | Yes | +| `--username ` | Bitbucket username (selects app-password auth) | - | Yes | +| `--password ` | Bitbucket app password (used with --username) | - | Yes | +| `--clone-url ` | HTTPS clone URL (generic provider) | - | Yes | +| `--token-username ` | HTTP Basic username for the token (generic; default x-access-token) | - | Yes | | `-y, --yes` | Skip confirmation prompts (for automation) | - | No | ### `providers remove` (alias: `rm`) @@ -574,27 +896,74 @@ Show Git provider details | `--id ` | Provider ID | - | Yes | | `--json` | Output in JSON format | - | No | +### `providers activate` + +Activate a Git provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | + +### `providers deactivate` + +Deactivate a Git provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | + +### `providers safe-delete` + +Safely delete a Git provider (checks dependencies first) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `providers deletion-check` + +Check if a Git provider can be safely deleted + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + ### `providers git` Manage Git providers **Subcommands:** -- `connect` - Connect a Git provider (github, gitlab) +- `connect` - Connect a Git provider (github, gitlab, bitbucket, gitea, generic) - `repos` - List available repositories #### `providers git connect` -Connect a Git provider (github, gitlab) +Connect a Git provider (github, gitlab, bitbucket, gitea, generic) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-p, --provider ` | Provider type (github, gitlab) | - | Yes | +| `-p, --provider ` | Provider type (github, gitlab, bitbucket, gitea, generic) | - | Yes | | `-n, --name ` | Provider name | - | Yes | -| `-t, --token ` | Personal access token | - | Yes | -| `--base-url ` | GitLab base URL (for self-hosted GitLab) | - | Yes | +| `-t, --token ` | Personal access token (or Bitbucket access token / app password) | - | Yes | +| `--base-url ` | Instance base URL (GitLab/Gitea self-hosted; required for gitea) | - | Yes | +| `--username ` | Bitbucket username (selects app-password auth) | - | Yes | +| `--password ` | Bitbucket app password (used with --username) | - | Yes | +| `--clone-url ` | HTTPS clone URL (generic provider) | - | Yes | +| `--token-username ` | HTTP Basic username for the token (generic; default x-access-token) | - | Yes | | `-y, --yes` | Skip confirmation prompts (for automation) | - | No | #### `providers git repos` @@ -607,59 +976,174 @@ List available repositories |------|-------------|---------|----------| | `--id ` | Provider ID (optional, lists all if not provided) | - | Yes | | `--json` | Output in JSON format | - | No | +| `--search ` | Search repositories by name | - | Yes | +| `--page ` | Page number | - | Yes | +| `--per-page ` | Items per page (max: 100) | - | Yes | +| `--sort ` | Sort by field (name, created_at, updated_at, stars) | - | Yes | +| `--direction ` | Sort direction: asc or desc | - | Yes | +| `--language ` | Filter by programming language | - | Yes | +| `--owner ` | Filter by repository owner | - | Yes | -## `backups` (alias: `backup`) - -Manage backup schedules and backups - -**Subcommands:** - -- `schedules` (`schedule`) - Manage backup schedules -- `list` (`ls`) - List backups for a schedule -- `show` - Show backup details - -### `backups schedules` (alias: `schedule`) +### `providers connections` (alias: `conn`) -Manage backup schedules +Manage Git provider connections **Subcommands:** -- `list` (`ls`) - List backup schedules -- `create` - Create a backup schedule -- `show` - Show backup schedule details -- `enable` - Enable a backup schedule -- `disable` - Disable a backup schedule -- `delete` (`rm`) - Delete a backup schedule +- `list` (`ls`) - List all Git connections +- `show` - Show connection details for a provider +- `delete` (`rm`) - Delete a Git connection +- `activate` - Activate a Git connection +- `deactivate` - Deactivate a Git connection +- `sync` - Sync repositories for a Git connection +- `update-token` - Update access token for a Git connection +- `validate` - Validate a Git connection -#### `backups schedules list` (alias: `ls`) +#### `providers connections list` (alias: `ls`) -List backup schedules +List all Git connections **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | +| `--page ` | Page number | - | Yes | +| `--per-page ` | Items per page (default: 30, max: 100) | - | Yes | +| `--sort ` | Sort by field (created_at, updated_at, account_name) | - | Yes | +| `--direction ` | Sort direction: asc or desc (default: desc) | - | Yes | -#### `backups schedules create` +#### `providers connections show` -Create a backup schedule +Show connection details for a provider **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-n, --name ` | Schedule name | - | Yes | -| `-t, --type ` | Backup type (full, incremental) | - | Yes | -| `-s, --schedule ` | Schedule expression (cron format) | - | Yes | -| `-r, --retention ` | Retention period in days | - | Yes | -| `-d, --description ` | Description | - | Yes | -| `--s3-source-id ` | S3 Source ID | - | Yes | -| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | -#### `backups schedules show` +#### `providers connections delete` (alias: `rm`) -Show backup schedule details +Delete a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +#### `providers connections activate` + +Activate a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | + +#### `providers connections deactivate` + +Deactivate a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | + +#### `providers connections sync` + +Sync repositories for a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | + +#### `providers connections update-token` + +Update access token for a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | +| `-t, --token ` | New access token | - | Yes | + +#### `providers connections validate` + +Validate a Git connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Connection ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +## `backups` (alias: `backup`) + +Manage backup schedules and backups + +**Subcommands:** + +- `schedules` (`schedule`) - Manage backup schedules +- `sources` (`source`) - Manage S3 backup sources +- `list` (`ls`) - List backups for a schedule +- `show` - Show backup details +- `delete` (`rm`) - Permanently delete one terminal backup +- `cleanup` - Delete backups expired by their schedule retention policy +- `run-service` - Run a backup for an external service + +### `backups schedules` (alias: `schedule`) + +Manage backup schedules + +**Subcommands:** + +- `list` (`ls`) - List backup schedules +- `create` - Create a backup schedule +- `show` - Show backup schedule details +- `enable` - Enable a backup schedule +- `disable` - Disable a backup schedule +- `delete` (`rm`) - Delete a backup schedule + +#### `backups schedules list` (alias: `ls`) + +List backup schedules + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +#### `backups schedules create` + +Create a backup schedule + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-n, --name ` | Schedule name | - | Yes | +| `-t, --type ` | Backup type (full, incremental) | - | Yes | +| `-s, --schedule ` | Schedule expression (cron format) | - | Yes | +| `-r, --retention ` | Retention period in days | - | Yes | +| `-d, --description ` | Description | - | Yes | +| `--s3-source-id ` | S3 Source ID | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +#### `backups schedules show` + +Show backup schedule details **Options:** @@ -700,6 +1184,108 @@ Delete a backup schedule | `-f, --force` | Skip confirmation | - | No | | `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | +### `backups sources` (alias: `source`) + +Manage S3 backup sources + +**Subcommands:** + +- `list` (`ls`) - List S3 sources +- `create` - Create an S3 source +- `show` - Show S3 source details +- `update` - Update an S3 source +- `remove` (`rm`) - Delete an S3 source +- `backups` - List backups for an S3 source +- `run` - Trigger a backup for an S3 source + +#### `backups sources list` (alias: `ls`) + +List S3 sources + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +#### `backups sources create` + +Create an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-n, --name ` | Source name | - | Yes | +| `--bucket ` | S3 bucket name | - | Yes | +| `--region ` | S3 region | - | Yes | +| `--endpoint ` | S3 endpoint (for S3-compatible services) | - | Yes | +| `--access-key ` | Access key ID | - | Yes | +| `--secret-key ` | Secret access key | - | Yes | +| `--prefix ` | Bucket path/prefix | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +#### `backups sources show` + +Show S3 source details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `backups sources update` + +Update an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | +| `-n, --name ` | New source name | - | Yes | +| `--bucket ` | New S3 bucket name | - | Yes | +| `--region ` | New S3 region | - | Yes | +| `--endpoint ` | New S3 endpoint | - | Yes | +| `--access-key ` | New access key ID | - | Yes | +| `--secret-key ` | New secret access key | - | Yes | +| `--prefix ` | New bucket path/prefix | - | Yes | + +#### `backups sources remove` (alias: `rm`) + +Delete an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +#### `backups sources backups` + +List backups for an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `backups sources run` + +Trigger a backup for an S3 source + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | S3 source ID | - | Yes | + ### `backups list` (alias: `ls`) List backups for a schedule @@ -722,9 +1308,46 @@ Show backup details | `--id ` | Backup ID | - | Yes | | `--json` | Output in JSON format | - | No | +### `backups delete` (alias: `rm`) + +Permanently delete one terminal backup + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Backup UUID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `backups cleanup` + +Delete backups expired by their schedule retention policy + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--dry-run` | Preview expired backups without deleting them | - | No | +| `--schedule-id ` | Limit cleanup to one schedule | - | Yes | +| `-y, --yes` | Skip confirmation prompt | - | No | +| `--json` | Output the cleanup report as JSON | - | No | + +### `backups run-service` + +Run a backup for an external service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | External service ID | - | Yes | +| `--s3-source-id ` | S3 source ID to store the backup | - | Yes | +| `-t, --type ` | Backup type (e.g., full, incremental) | - | Yes | + ## `runtime-logs` (alias: `rlogs`) -Stream runtime container logs (not build logs) +View runtime container logs (use -f to follow in real-time) **Options:** @@ -735,15 +1358,19 @@ Stream runtime container logs (not build logs) | `-c, --container ` | Container ID (partial match supported) | - | Yes | | `-n, --tail ` | Number of lines to tail | `1000` | Yes | | `-t, --timestamps` | Show timestamps | - | No | +| `-f, --follow` | Follow log output (stream in real-time) | - | No | ## `notifications` (alias: `notify`) -Manage notification providers (Slack, Email, etc.) +Manage notification providers (Slack, Email, Webhook, etc.) **Subcommands:** - `list` (`ls`) - List configured notification providers - `add` - Add a new notification provider +- `update` - Update a notification provider +- `enable` - Enable a notification provider +- `disable` - Disable a notification provider - `show` - Show notification provider details - `remove` (`rm`) - Remove a notification provider - `test` - Send a test notification @@ -760,249 +1387,535 @@ List configured notification providers ### `notifications add` -Add a new notification provider +Add a new notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-t, --type ` | Provider type (slack, email, webhook) | - | Yes | +| `-n, --name ` | Provider name | - | Yes | +| `-w, --webhook-url ` | Webhook URL (for slack) | - | Yes | +| `-c, --channel ` | Channel name (for slack, optional) | - | Yes | +| `--smtp-host ` | SMTP host (for email) | - | Yes | +| `--smtp-port ` | SMTP port (for email) | - | Yes | +| `--username ` | SMTP username (for email) | - | Yes | +| `--password ` | SMTP password (for email) | - | Yes | +| `--from-address
` | From email address (for email) | - | Yes | +| `--from-name ` | From display name (for email, optional) | - | Yes | +| `--to-addresses ` | Comma-separated recipient addresses (for email) | - | Yes | +| `--url ` | Webhook URL (for webhook) | - | Yes | +| `--method ` | HTTP method: POST, PUT, PATCH (for webhook, default: POST) | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +### `notifications update` + +Update a notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `-n, --name ` | New provider name | - | Yes | +| `--enabled ` | Enable or disable (true/false) | - | Yes | +| `-w, --webhook-url ` | Webhook URL (for slack) | - | Yes | +| `-c, --channel ` | Channel name (for slack) | - | Yes | +| `--smtp-host ` | SMTP host (for email) | - | Yes | +| `--smtp-port ` | SMTP port (for email) | - | Yes | +| `--username ` | SMTP username (for email) | - | Yes | +| `--password ` | SMTP password (for email) | - | Yes | +| `--from-address
` | From email address (for email) | - | Yes | +| `--from-name ` | From display name (for email) | - | Yes | +| `--to-addresses ` | Comma-separated recipient addresses (for email) | - | Yes | +| `--url ` | Webhook URL (for webhook) | - | Yes | +| `--method ` | HTTP method: POST, PUT, PATCH (for webhook) | - | Yes | +| `--json` | Output in JSON format | - | No | +| `-y, --yes` | Skip confirmation prompts | - | No | + +### `notifications enable` + +Enable a notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `notifications disable` + +Disable a notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `notifications show` + +Show notification provider details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `notifications remove` (alias: `rm`) + +Remove a notification provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `notifications test` + +Send a test notification + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | + +## `dns` + +Manage DNS providers for automated domain verification + +**Subcommands:** + +- `list` (`ls`) - List configured DNS providers +- `add` - Add a new DNS provider +- `show` - Show DNS provider details +- `remove` (`rm`) - Remove a DNS provider +- `test` - Test DNS provider connection +- `zones` - List available zones in a DNS provider + +### `dns list` (alias: `ls`) + +List configured DNS providers + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +### `dns add` + +Add a new DNS provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-t, --type ` | Provider type (cloudflare, route53, digitalocean, namecheap, gcp, azure, manual) | - | Yes | +| `-n, --name ` | Provider name | - | Yes | +| `-d, --description ` | Provider description | - | Yes | +| `--api-token ` | Cloudflare API token | - | Yes | +| `--account-id ` | Cloudflare account ID (optional) | - | Yes | +| `--access-key-id ` | AWS access key ID | - | Yes | +| `--secret-access-key ` | AWS secret access key | - | Yes | +| `--region ` | AWS region | - | Yes | +| `--api-user ` | Namecheap API user | - | Yes | +| `--api-key ` | Namecheap API key | - | Yes | +| `--username ` | Namecheap username | - | Yes | +| `--client-ip ` | Namecheap whitelisted client IP | - | Yes | +| `--project-id ` | GCP project ID | - | Yes | +| `--service-account-email ` | GCP service account email | - | Yes | +| `--private-key-id ` | GCP private key ID | - | Yes | +| `--private-key ` | GCP private key | - | Yes | +| `--tenant-id ` | Azure tenant ID | - | Yes | +| `--client-id ` | Azure client ID | - | Yes | +| `--client-secret ` | Azure client secret | - | Yes | +| `--subscription-id ` | Azure subscription ID | - | Yes | +| `--resource-group ` | Azure resource group | - | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +### `dns show` + +Show DNS provider details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `dns remove` (alias: `rm`) + +Remove a DNS provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation (alias for --force) | - | No | + +### `dns test` + +Test DNS provider connection + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | + +### `dns zones` + +List available zones in a DNS provider + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Provider ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +## `services` (alias: `svc`) + +Manage external services (databases, caches, storage) + +**Subcommands:** + +- `list` (`ls`) - List all external services +- `create` (`add`) - Create a new external service +- `show` - Show service details +- `remove` (`rm`) - Remove a service +- `start` - Start a stopped service +- `stop` - Stop a running service +- `types` - List available service types +- `projects` - List projects linked to a service +- `update` - Update a service +- `upgrade` - Upgrade a service to a newer version +- `import` - Import an existing external service +- `link` - Link a service to a project +- `unlink` - Unlink a service from a project +- `connect` - Get connection info for a service by name or slug +- `env` - Show environment variables for a linked service +- `env-var` - Get a specific environment variable +- `logs` - View persisted logs for an external service +- `slow-queries` - Show slowest PostgreSQL queries from pg_stat_statements +- `enable-pg-stat-statements` - Enable pg_stat_statements on a standalone Postgres service by restarting its container (drops active connections briefly) +- `restore-capabilities` - Show what restore modes a service supports (in-place / new service / PITR) +- `list-backups` - List backups stored on an S3 source +- `restore` - Restore a service from a backup (in-place, new service, or PITR) +- `restore-runs` - List recent restore runs for a service +- `restore-run` - Show a single restore run + +### `services list` (alias: `ls`) + +List all external services + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--json` | Output in JSON format | - | No | + +### `services create` (alias: `add`) + +Create a new external service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-t, --type ` | Service type (postgres, mongodb, redis, s3) | - | Yes | +| `-n, --name ` | Service name | - | Yes | +| `-s, --set ` | Set a parameter (repeatable) | `` | Yes | +| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | + +### `services show` + +Show service details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `services remove` (alias: `rm`) + +Remove a service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-f, --force` | Skip confirmation | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | + +### `services start` + +Start a stopped service + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | + +### `services stop` + +Stop a running service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-t, --type ` | Provider type (slack, discord) | - | Yes | -| `-n, --name ` | Provider name | - | Yes | -| `-w, --webhook-url ` | Webhook URL | - | Yes | -| `-c, --channel ` | Channel name (optional) | - | Yes | -| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--id ` | Service ID | - | Yes | -### `notifications show` +### `services types` -Show notification provider details +List available service types **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Provider ID | - | Yes | | `--json` | Output in JSON format | - | No | -### `notifications remove` (alias: `rm`) +**Subcommands:** -Remove a notification provider +- `info` - Show parameters schema for a service type (useful for automation) + +#### `services types info` + +Show parameters schema for a service type (useful for automation) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Provider ID | - | Yes | -| `-f, --force` | Skip confirmation | - | No | -| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | +| `--json` | Output as raw JSON schema (default) | - | No | -### `notifications test` +### `services projects` -Send a test notification +List projects linked to a service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Provider ID | - | Yes | +| `--id ` | Service ID | - | Yes | +| `--json` | Output in JSON format | - | No | -## `dns` (alias: `dns-providers`) +### `services update` -Manage DNS providers for automated domain verification +Update a service -**Subcommands:** +**Options:** -- `list` (`ls`) - List configured DNS providers -- `add` - Add a new DNS provider -- `show` - Show DNS provider details -- `remove` (`rm`) - Remove a DNS provider -- `test` - Test DNS provider connection -- `zones` - List available zones in a DNS provider +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-n, --name ` | Docker image name (e.g., postgres:18-alpine) | - | Yes | +| `-s, --set ` | Set a parameter (repeatable) | `` | Yes | -### `dns list` (alias: `ls`) +### `services upgrade` -List configured DNS providers +Upgrade a service to a newer version **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output in JSON format | - | No | +| `--id ` | Service ID | - | Yes | +| `-v, --version ` | Docker image to upgrade to (e.g., postgres:18-alpine) | - | Yes | -### `dns add` +### `services import` -Add a new DNS provider +Import an existing external service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-t, --type ` | Provider type (cloudflare, route53, digitalocean, namecheap, gcp, azure, manual) | - | Yes | -| `-n, --name ` | Provider name | - | Yes | -| `-d, --description ` | Provider description | - | Yes | -| `--api-token ` | Cloudflare API token | - | Yes | -| `--account-id ` | Cloudflare account ID (optional) | - | Yes | -| `--access-key-id ` | AWS access key ID | - | Yes | -| `--secret-access-key ` | AWS secret access key | - | Yes | -| `--region ` | AWS region | - | Yes | -| `--api-user ` | Namecheap API user | - | Yes | -| `--api-key ` | Namecheap API key | - | Yes | -| `--username ` | Namecheap username | - | Yes | -| `--client-ip ` | Namecheap whitelisted client IP | - | Yes | -| `--project-id ` | GCP project ID | - | Yes | -| `--service-account-email ` | GCP service account email | - | Yes | -| `--private-key-id ` | GCP private key ID | - | Yes | -| `--private-key ` | GCP private key | - | Yes | -| `--tenant-id ` | Azure tenant ID | - | Yes | -| `--client-id ` | Azure client ID | - | Yes | -| `--client-secret ` | Azure client secret | - | Yes | -| `--subscription-id ` | Azure subscription ID | - | Yes | -| `--resource-group ` | Azure resource group | - | Yes | +| `-t, --type ` | Service type (postgres, mongodb, redis, s3) | - | Yes | +| `-n, --name ` | Service name | - | Yes | +| `--container-id ` | Container ID or name to import | - | Yes | +| `-s, --set ` | Set a parameter (repeatable) | `` | Yes | +| `--version ` | Optional version override | - | Yes | | `-y, --yes` | Skip confirmation prompts (for automation) | - | No | -### `dns show` +### `services link` -Show DNS provider details +Link a service to a project **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Provider ID | - | Yes | -| `--json` | Output in JSON format | - | No | +| `--id ` | Service ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | -### `dns remove` (alias: `rm`) +### `services unlink` -Remove a DNS provider +Unlink a service from a project **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Provider ID | - | Yes | +| `--id ` | Service ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | | `-f, --force` | Skip confirmation | - | No | -| `-y, --yes` | Skip confirmation (alias for --force) | - | No | +| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | -### `dns test` +### `services connect` -Test DNS provider connection +Get connection info for a service by name or slug **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Provider ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | +| `--json` | Output in JSON format | - | No | -### `dns zones` +### `services env` -List available zones in a DNS provider +Show environment variables for a linked service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Provider ID | - | Yes | +| `--id ` | Service ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | | `--json` | Output in JSON format | - | No | -## `services` (alias: `svc`) +### `services env-var` -Manage external services (databases, caches, storage) +Get a specific environment variable -**Subcommands:** +**Options:** -- `list` (`ls`) - List all external services -- `create` (`add`) - Create a new external service -- `show` - Show service details -- `remove` (`rm`) - Remove a service -- `start` - Start a stopped service -- `stop` - Stop a running service -- `types` - List available service types -- `projects` - List projects linked to a service +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json) | - | Yes | +| `--var ` | Environment variable name | - | Yes | +| `--json` | Output in JSON format | - | No | -### `services list` (alias: `ls`) +### `services logs` -List all external services +View persisted logs for an external service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--json` | Output in JSON format | - | No | +| `--id ` | Service ID | - | Yes | +| `--from ` | Start of time range. ISO 8601 timestamp or a relative duration like "1h", "24h", "7d" (default: 24h ago) | - | Yes | +| `--to ` | End of time range. ISO 8601 timestamp (default: now) | - | Yes | +| `-l, --level ` | Comma-separated log levels to include: ERROR,WARN,INFO,DEBUG,TRACE | - | Yes | +| `-n, --tail ` | Maximum number of log lines to fetch (default: 200, max: 1000) | `200` | Yes | +| `-t, --text ` | Filter log lines by text (case-insensitive) | - | Yes | +| `--json` | Output raw JSON instead of formatted lines | - | No | -### `services create` (alias: `add`) +### `services slow-queries` -Create a new external service +Show slowest PostgreSQL queries from pg_stat_statements **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `-t, --type ` | Service type (postgres, mongodb, redis, s3) | - | Yes | -| `-n, --name ` | Service name | - | Yes | -| `--parameters ` | Service parameters as JSON string | - | Yes | -| `-y, --yes` | Skip confirmation prompts (for automation) | - | No | +| `--id ` | Service ID | - | Yes | +| `--page ` | Page number (1-based, default: 1) | `1` | Yes | +| `--page-size ` | Rows per page (1–100, default: 20) | `20` | Yes | +| `--sort-by ` | Sort column: calls, total_exec_time_ms, mean_exec_time_ms, rows, cache_hit_ratio (default: mean_exec_time_ms) | - | Yes | +| `--sort-order ` | Sort direction: asc or desc (default: desc) | - | Yes | +| `--json` | Output raw JSON instead of a formatted table | - | No | -### `services show` +### `services enable-pg-stat-statements` -Show service details +Enable pg_stat_statements on a standalone Postgres service by restarting its container (drops active connections briefly) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| | `--id ` | Service ID | - | Yes | -| `--json` | Output in JSON format | - | No | +| `-y, --yes` | Skip the restart confirmation prompt (for automation) | - | No | -### `services remove` (alias: `rm`) +### `services restore-capabilities` -Remove a service +Show what restore modes a service supports (in-place / new service / PITR) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| | `--id ` | Service ID | - | Yes | -| `-f, --force` | Skip confirmation | - | No | -| `-y, --yes` | Skip confirmation prompts (alias for --force) | - | No | +| `--json` | Output in JSON format | - | No | -### `services start` +### `services list-backups` -Start a stopped service +List backups stored on an S3 source **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Service ID | - | Yes | +| `--s3-source-id ` | S3 source ID | - | Yes | +| `--json` | Output in JSON format | - | No | -### `services stop` +### `services restore` -Stop a running service +Restore a service from a backup (in-place, new service, or PITR) **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Service ID | - | Yes | +| `--id ` | Source service ID (the service the backup came from) | - | Yes | +| `--backup-id ` | Backup ID to restore from (see `list-backups`) | - | Yes | +| `--new-service [name]` | Clone into a new service. Omit the value or pass "auto" to accept the auto-suggested name. | - | No | +| `--pitr ` | Point-in-time recovery target, ISO 8601 timestamp (requires WAL-G backup). Combine with --new-service to route PITR into a new service. | - | Yes | +| `-y, --yes` | Skip confirmation | - | No | +| `--no-wait` | Return immediately without polling run status | - | No | +| `--json` | Output in JSON format | - | No | -### `services types` +### `services restore-runs` -List available service types +List recent restore runs for a service **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| +| `--id ` | Service ID | - | Yes | | `--json` | Output in JSON format | - | No | -### `services projects` +### `services restore-run` -List projects linked to a service +Show a single restore run **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Service ID | - | Yes | +| `--id ` | Restore run ID | - | Yes | | `--json` | Output in JSON format | - | No | ## `settings` @@ -1237,7 +2150,7 @@ List available API key permissions |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | -## `monitors` +## `monitors` (alias: `monitoring`) Manage uptime monitors for status pages @@ -1247,7 +2160,7 @@ Manage uptime monitors for status pages - `create` (`add`) - Create a new monitor for a project - `show` - Show monitor details and current status - `remove` (`rm`) - Delete a monitor -- `status` - Get current monitor status +- `status` - Get current status — all monitors for a project, or a single monitor by ID - `history` - Get monitor uptime history ### `monitors list` (alias: `ls`) @@ -1273,6 +2186,7 @@ Create a new monitor for a project | `-n, --name ` | Monitor name | - | Yes | | `-t, --type ` | Monitor type (http, tcp, ping) | - | Yes | | `-i, --interval ` | Check interval in seconds (60, 300, 600, 900, 1800) | - | Yes | +| `--check-path ` | HTTP health-check path (must start with "/", e.g. /api/healthz). Defaults to "/" for HTTP monitors. | - | Yes | | `--environment-id ` | Environment ID (default: 0 for production) | - | Yes | | `-y, --yes` | Skip confirmation prompts (for automation) | - | No | @@ -1301,13 +2215,14 @@ Delete a monitor ### `monitors status` -Get current monitor status +Get current status — all monitors for a project, or a single monitor by ID **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| -| `--id ` | Monitor ID | - | Yes | +| `--id ` | Monitor ID (omit to show all monitors for the project) | - | Yes | +| `-p, --project ` | Project slug (auto-detected from .temps/config.json or TEMPS_PROJECT) | - | Yes | | `--json` | Output in JSON format | - | No | ### `monitors history` @@ -1331,10 +2246,12 @@ Manage webhooks for project events - `list` (`ls`) - List all webhooks for a project - `create` (`add`) - Create a new webhook for a project - `show` - Show webhook details +- `update` - Update a webhook - `remove` (`rm`) - Delete a webhook - `enable` - Enable a webhook - `disable` - Disable a webhook - `events` - List available webhook event types +- `deliveries` - Manage webhook deliveries ### `webhooks list` (alias: `ls`) @@ -1373,6 +2290,20 @@ Show webhook details | `--webhook-id ` | Webhook ID | - | Yes | | `--json` | Output in JSON format | - | No | +### `webhooks update` + +Update a webhook + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | +| `-u, --url ` | New webhook URL | - | Yes | +| `-e, --events ` | Comma-separated event types (or "all" for all events) | - | Yes | +| `-s, --secret ` | New webhook secret for signature verification | - | Yes | + ### `webhooks remove` (alias: `rm`) Delete a webhook @@ -1418,13 +2349,61 @@ List available webhook event types |------|-------------|---------|----------| | `--json` | Output in JSON format | - | No | +### `webhooks deliveries` + +Manage webhook deliveries + +**Subcommands:** + +- `list` (`ls`) - List deliveries for a webhook +- `show` - Show delivery details +- `retry` - Retry a failed delivery + +#### `webhooks deliveries list` (alias: `ls`) + +List deliveries for a webhook + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | +| `--limit ` | Number of deliveries to return (default: 50) | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `webhooks deliveries show` + +Show delivery details + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | +| `--delivery-id ` | Delivery ID | - | Yes | +| `--json` | Output in JSON format | - | No | + +#### `webhooks deliveries retry` + +Retry a failed delivery + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `--project-id ` | Project ID | - | Yes | +| `--webhook-id ` | Webhook ID | - | Yes | +| `--delivery-id ` | Delivery ID | - | Yes | + ## `containers` (alias: `cts`) Manage project containers in environments **Subcommands:** -- `list` (`ls`) - List all containers in an environment +- `list` (`ls`) - List containers in an environment, or across all environments if -e omitted - `show` - Show container details - `start` - Start a stopped container - `stop` - Stop a running container @@ -1433,14 +2412,14 @@ Manage project containers in environments ### `containers list` (alias: `ls`) -List all containers in an environment +List containers in an environment, or across all environments if -e omitted **Options:** | Flag | Description | Default | Required | |------|-------------|---------|----------| | `-p, --project-id ` | Project ID | - | Yes | -| `-e, --environment-id ` | Environment ID | - | Yes | +| `-e, --environment-id ` | Environment ID (optional - lists all environments if omitted) | - | Yes | | `--json` | Output in JSON format | - | No | ### `containers show` @@ -1508,50 +2487,133 @@ Get container resource metrics (all containers if no container ID specified) | `-w, --watch` | Watch mode - continuously update metrics | - | No | | `-i, --interval ` | Refresh interval in seconds (default: 2) | `2` | Yes | +## `flags` (alias: `flag`) ---- +Manage feature flags (runtime config that changes without a redeploy) -## `analytics` (alias: `stats`) +**Subcommands:** -View project analytics from the terminal. +- `list` (`ls`) - List feature flags +- `get` - Show a feature flag and its per-environment values +- `create` - Create a feature flag +- `update` - Update a flag definition (default value, description, visibility) +- `set` - Set a flag value in one environment +- `clear` - Clear a flag override so the environment inherits the default +- `disable` - Kill switch: serve the default in this environment, ignoring any override +- `enable` - Re-enable a flag in this environment after a kill switch +- `archive` - Archive a flag (callers fall back to their own default) -**Subcommands:** +### `flags list` (alias: `ls`) -- `overview` (`o`) - Show analytics dashboard overview -- `top ` - Show breakdown by dimension +List feature flags -### `analytics overview` (alias: `o`) +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Show values for this environment | - | Yes | +| `--include-archived` | Include archived flags | - | No | +| `--page ` | Page number (default: 1) | - | Yes | +| `--page-size ` | Items per page (default: 20, max: 100) | - | Yes | +| `--json` | Output in JSON format | - | No | -Show analytics dashboard overview with key metrics, hourly sparkline, top pages, events, and locations. +### `flags get` -| Flag | Description | Default | -|------|-------------|---------| -| `-p, --project ` | Project slug or ID | - | -| `--period ` | Time period: today, 24h, 7d, 30d, 90d | `24h` | -| `--json` | Output in JSON format | - | +Show a feature flag and its per-environment values -```bash -temps analytics overview -p my-app --period 7d -temps stats -p my-app -``` +**Options:** -### `analytics top ` +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `--json` | Output in JSON format | - | No | -Show breakdown by dimension: `pages`, `referrers`, `browsers`, `os`, `devices`, `countries`, `channels`, `events`, `languages`, `utm_source`, `utm_medium`, `utm_campaign` +### `flags create` -| Flag | Description | Default | -|------|-------------|---------| -| `-p, --project ` | Project slug or ID | - | -| `--period ` | Time period: today, 24h, 7d, 30d, 90d | `24h` | -| `--limit ` | Number of results | `20` | -| `--json` | Output in JSON format | - | +Create a feature flag + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-t, --type ` | Value type: bool, string, number, or json | - | Yes | +| `-d, --default ` | Default value, served when nothing more specific applies | - | Yes | +| `--description ` | What this flag controls | - | Yes | +| `--client-visible` | Allow this flag to be exposed to browsers (default: server-only) | - | No | +| `--json` | Output in JSON format | - | No | + +### `flags update` + +Update a flag definition (default value, description, visibility) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-d, --default ` | New default value | - | Yes | +| `--description ` | New description | - | Yes | +| `--client-visible` | Expose this flag to browsers | - | No | +| `--no-client-visible` | Make this flag server-only | - | No | +| `--json` | Output in JSON format | - | No | + +### `flags set` + +Set a flag value in one environment + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | +| `--json` | Output in JSON format | - | No | + +### `flags clear` + +Clear a flag override so the environment inherits the default + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | + +### `flags disable` + +Kill switch: serve the default in this environment, ignoring any override + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | + +### `flags enable` + +Re-enable a flag in this environment after a kill switch + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | +| `-e, --environment ` | Environment name or slug | - | Yes | + +### `flags archive` + +Archive a flag (callers fall back to their own default) + +**Options:** + +| Flag | Description | Default | Required | +|------|-------------|---------|----------| +| `-p, --project ` | Project slug or ID | - | Yes | -```bash -temps analytics top pages -p my-app --period 30d -temps analytics top referrers --period 7d -temps analytics top browsers --json -temps analytics top countries --limit 50 -``` --- @@ -1620,9 +2682,9 @@ The CLI respects the following environment variables: Configuration is stored in: - **Config file**: `~/.temps/config.json` -- **Credentials**: stored securely under `~/.temps/` with restricted permissions (mode 0600), managed by `login`/`logout` +- **Credentials**: Stored securely in `~/.temps/` with restricted file permissions -Use `temps configure show` to view current configuration. +Use `bunx @temps-sdk/cli configure show` to view current configuration. ## Support diff --git a/apps/temps-cli/openapi.json b/apps/temps-cli/openapi.json index bdcf3b6de..9565b27d7 100644 --- a/apps/temps-cli/openapi.json +++ b/apps/temps-cli/openapi.json @@ -1 +1 @@ -{"openapi":"3.1.0","info":{"title":"Temps","description":"An API for managing projects, deployments, and infrastructure resources","contact":{"name":"Temps Support","url":"https://temps.sh"},"version":"1.0.0"},"servers":[{"url":"/api","description":"Base path for all API endpoints"}],"paths":{"/.well-known/temps.json":{"get":{"tags":["Platform"],"summary":"Get platform information","operationId":"get_platform_info","responses":{"200":{"description":"Successfully retrieved platform information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformInfo"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/0/organizations/{org_slug}/chunk-upload/":{"get":{"tags":["sentry-compat"],"summary":"Chunk upload options (stub for sentry-cli compatibility).","description":"sentry-cli checks this endpoint to determine if chunk-based upload is supported.\nWe return a response indicating that chunk upload is NOT supported, which forces\nsentry-cli to fall back to the standard file-by-file upload.","operationId":"chunk_upload_options","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Chunk upload options","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryChunkUploadResponse"}}}}}}},"/0/organizations/{org_slug}/releases/":{"post":{"tags":["sentry-compat"],"summary":"Create a release (stub for sentry-cli compatibility).","description":"sentry-cli calls this before uploading files. Since Temps implicitly creates\nreleases when source maps are uploaded, this is a no-op that returns the\nexpected response format.","operationId":"create_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored in single-tenant mode)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryCreateReleaseRequest"}}},"required":true},"responses":{"201":{"description":"Release created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"}}}},"/0/projects/{org_slug}/{project_slug}/releases/":{"post":{"tags":["sentry-compat"],"summary":"Create a release for a specific project (stub for sentry-cli compatibility).","description":"sentry-cli calls this endpoint (instead of /organizations/.../releases/) when\nboth SENTRY_ORG and SENTRY_PROJECT env vars are set. Behaves identically to\nthe organizations endpoint but validates the project slug.","operationId":"create_project_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored in single-tenant mode)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryCreateReleaseRequest"}}},"required":true},"responses":{"201":{"description":"Release created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}}},"/0/projects/{org_slug}/{project_slug}/releases/{version}/":{"put":{"tags":["sentry-compat"],"summary":"Finalize a release (stub for sentry-cli compatibility).","description":"sentry-cli calls `releases finalize` after uploading source maps. This sets\nthe dateReleased on the release. Since Temps stores source maps independently\nof releases, this is a no-op that returns the expected response.","operationId":"finalize_project_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version to finalize","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Release finalized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}}},"/0/projects/{org_slug}/{project_slug}/releases/{version}/files/":{"get":{"tags":["sentry-compat"],"summary":"List files for a release.","description":"Returns all source maps stored for a specific release in sentry-cli compatible format.","operationId":"list_release_files","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of release files","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SentryReleaseFileResponse"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}},"post":{"tags":["sentry-compat"],"summary":"Upload a source map file for a release.","description":"Accepts the same multipart format as the Sentry release files API.\nThe `name` field should be the URL path of the file (e.g., `~/dist/bundle.js.map`).\n\nThe route has a 50 MiB body limit applied at the router level (Fix #4).\nA per-field size check provides an additional defense-in-depth layer.","operationId":"upload_release_file","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"File uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseFileResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"},"413":{"description":"Source map file exceeds the 50 MiB per-field limit"}}}},"/_temps/event":{"post":{"tags":["Metrics"],"summary":"Record analytics event","operationId":"record_event_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Event recorded successfully"},"400":{"description":"Bad request"},"500":{"description":"Internal server error"}}}},"/_temps/session-replay/events":{"post":{"tags":["Analytics"],"summary":"Add events to existing session replay","operationId":"add_session_replay_events","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayEventsRequest"}}},"required":true},"responses":{"200":{"description":"Events added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/session-replay/init":{"post":{"tags":["Analytics"],"summary":"Initialize session replay with metadata","operationId":"init_session_replay","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayInitRequest"}}},"required":true},"responses":{"201":{"description":"Session initialized successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayInitResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/speed":{"post":{"tags":["Performance"],"summary":"Record performance metrics from client","operationId":"record_speed_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeedMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Metrics recorded successfully"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Host not found in route table","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/speed/update":{"post":{"tags":["Performance"],"summary":"Update late performance metrics","operationId":"update_speed_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSpeedMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Metrics updated successfully"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Host not found or metrics not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/admin/gate-settings":{"get":{"tags":["AdminGate"],"operationId":"get_admin_gate","responses":{"200":{"description":"Current admin gate config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AdminGate"],"operationId":"patch_admin_gate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAdminGateRequest"}}},"required":true},"responses":{"200":{"description":"Updated admin gate config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGateResponse"}}}},"400":{"description":"Invalid IP/CIDR/host"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Env-overridden or would lock out caller"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers":{"get":{"tags":["Authentication"],"operationId":"list_oidc_providers","responses":{"200":{"description":"OIDC providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Authentication"],"operationId":"create_oidc_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOidcProviderRequest"}}},"required":true},"responses":{"201":{"description":"OIDC provider created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProviderResponse"}}}},"409":{"description":"Another OIDC provider already uses that name"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}":{"delete":{"tags":["Authentication"],"operationId":"delete_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"OIDC provider deleted"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Authentication"],"operationId":"update_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOidcProviderRequest"}}},"required":true},"responses":{"200":{"description":"OIDC provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProviderResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/role-mappings":{"get":{"tags":["Authentication"],"operationId":"list_oidc_role_mappings","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"OIDC role mappings","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcRoleMappingResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Authentication"],"operationId":"create_oidc_role_mapping","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOidcRoleMappingRequest"}}},"required":true},"responses":{"201":{"description":"Role mapping created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRoleMappingResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/test":{"post":{"tags":["Authentication"],"operationId":"test_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcTestConnectionResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/users":{"get":{"tags":["Authentication"],"operationId":"list_oidc_provider_users","parameters":[{"name":"provider_id","in":"path","description":"OIDC provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Users authenticated via this OIDC provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderUserResponse"}}}}},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/role-mappings/{mapping_id}":{"delete":{"tags":["Authentication"],"operationId":"delete_oidc_role_mapping","parameters":[{"name":"mapping_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Role mapping deleted"}},"security":[{"bearer_auth":[]}]}},"/agents/webhook/{webhook_id}":{"post":{"tags":["Agents"],"summary":"Public webhook endpoint. Authenticated via `X-Webhook-Token` header.","description":"`POST /api/agents/webhook/{webhook_id}`\nHeader: `X-Webhook-Token: `\n\nThe `webhook_id` in the URL is a short non-secret identifier (safe to log).\nThe actual credential is the secret token in the header.\n\nAccepts any JSON body, which is passed as `user_context` to the agent run.","operationId":"webhook_trigger","parameters":[{"name":"webhook_id","in":"path","description":"Webhook ID (non-secret)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTriggerRequest"}}},"required":true},"responses":{"202":{"description":"Agent run created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTriggerResponse"}}}},"401":{"description":"Missing or invalid X-Webhook-Token header"},"404":{"description":"Invalid webhook ID"},"422":{"description":"Agent disabled"}}}},"/ai/conversations":{"get":{"tags":["AI Chat"],"summary":"List every active conversation across all projects, most-recently-active\nfirst, annotated with project name/slug. Powers the unified \"all chats\"\nswitcher in the AI assistant dock.","operationId":"list_all_conversations","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GlobalConversationResponse"}}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]}},"/ai/pricing":{"get":{"tags":["AI Gateway Pricing"],"operationId":"get_pricing","responses":{"200":{"description":"Model pricing information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers":{"get":{"tags":["AI Gateway Admin"],"operationId":"list_provider_keys","responses":{"200":{"description":"List of provider keys","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["AI Gateway Admin"],"operationId":"create_provider_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderKeyRequest"}}},"required":true},"responses":{"201":{"description":"Provider key created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/test":{"post":{"tags":["AI Gateway Admin"],"operationId":"test_provider_key_inline","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyRequest"}}},"required":true},"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/{id}":{"delete":{"tags":["AI Gateway Admin"],"operationId":"delete_provider_key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider key deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AI Gateway Admin"],"operationId":"update_provider_key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderKeyRequest"}}},"required":true},"responses":{"200":{"description":"Provider key updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/{id}/test":{"post":{"tags":["AI Gateway Admin"],"operationId":"test_provider_key_by_id","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Provider key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/by-provider":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_by_provider","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Usage broken down by provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderUsage"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/conversations":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_conversations","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 50, max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"user_id","in":"query","description":"Filter by user ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"tags","in":"query","description":"Filter by tags (comma-separated)","required":false,"schema":{"type":"string"}},{"name":"model","in":"query","description":"Filter by model name","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Conversation summaries","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationSummary"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/conversations/{conversation_id}":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_conversation_detail","parameters":[{"name":"conversation_id","in":"path","description":"Conversation ID","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Invocations within a conversation","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsageLogEntry"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/recent":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_recent","parameters":[{"name":"limit","in":"query","description":"Page size (defaults to 20, max 50)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Number of results to skip for pagination (defaults to 0)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"provider","in":"query","description":"Filter by provider name","required":false,"schema":{"type":"string"}},{"name":"model","in":"query","description":"Filter by model name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by HTTP status code (exact match)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"cost_gte","in":"query","description":"Cost greater-than-or-equal, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_gt","in":"query","description":"Cost strictly greater-than, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_lte","in":"query","description":"Cost less-than-or-equal, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_lt","in":"query","description":"Cost strictly less-than, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_gte","in":"query","description":"Total tokens greater-than-or-equal","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_gt","in":"query","description":"Total tokens strictly greater-than","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_lte","in":"query","description":"Total tokens less-than-or-equal","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_lt","in":"query","description":"Total tokens strictly less-than","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Page of recent usage log entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageLogPage"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/summary":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_summary","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Usage summary for the time range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/timeseries":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_timeseries","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"bucket","in":"query","description":"Bucket size: hour, day, week (defaults to day)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Time-series usage data","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TimeseriesBucket"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/top-models":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_top_models","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 10)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Top models by request count","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ModelUsage"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/chat/completions":{"post":{"tags":["AI Gateway"],"operationId":"chat_completions","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}},"required":true},"responses":{"200":{"description":"Chat completion response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"404":{"description":"Model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/embeddings":{"post":{"tags":["AI Gateway"],"operationId":"embeddings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingRequest"}}},"required":true},"responses":{"200":{"description":"Embedding response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"404":{"description":"Model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/models":{"get":{"tags":["AI Gateway"],"operationId":"list_models","responses":{"200":{"description":"List of available models","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/analytics/active-visitors":{"get":{"tags":["Analytics"],"summary":"Get detailed active visitors","operationId":"get_analytics_active_visitors","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"window_minutes","in":"query","description":"Time window in minutes for active visitors (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved active visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveVisitorsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-detail":{"get":{"tags":["Analytics"],"summary":"Get detailed analytics for a specific event","operationId":"get_event_detail","parameters":[{"name":"event_name","in":"query","description":"Event name to get details for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval: hour, day, week, month (default: auto)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventDetailResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-entries":{"get":{"tags":["Analytics"],"summary":"Get paginated list of raw occurrences of a specific event, including custom JSON properties","operationId":"get_event_entries","parameters":[{"name":"event_name","in":"query","description":"Event name to list occurrences for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved event entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventEntriesResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-visitors":{"get":{"tags":["Analytics"],"summary":"Get paginated list of visitors who triggered a specific event","operationId":"get_event_visitors","parameters":[{"name":"event_name","in":"query","description":"Event name to list visitors for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved event visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventVisitorsResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/events":{"get":{"tags":["Analytics"],"operationId":"get_analytics_events_count","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of results to return","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"custom_events_only","in":"query","description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"breakdown","in":"query","description":"Breakdown by geography: 'country', 'region', or 'city' (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event counts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventCount"}}}}},"400":{"description":"Invalid date format, missing required parameters, or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/general-stats":{"get":{"tags":["Analytics"],"summary":"Get general statistics across all projects for a time frame","operationId":"get_general_stats","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_ids","in":"query","description":"Optional: Filter by specific project IDs (comma-separated)","required":false,"schema":{"type":"array","items":{"type":"integer","format":"int32"}}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_project_breakdown","in":"query","description":"Whether to include per-project breakdown (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successfully retrieved general statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneralStatsResponse"}}}},"400":{"description":"Invalid date format or parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/has-events":{"get":{"tags":["Analytics"],"operationId":"check_analytics_has_events","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Analytics events existence check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasAnalyticsEventsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/live-visitors":{"get":{"tags":["Analytics"],"summary":"Get list of currently live visitors from visitor table","operationId":"get_live_visitors_list","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"window_minutes","in":"query","description":"Time window in minutes for live visitors (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved live visitors list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveVisitorsListResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-flow":{"get":{"tags":["Analytics"],"summary":"Get page flow analytics: entry pages, exit pages, drop-off points, and page transitions","operationId":"get_page_flow","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max entry/exit pages to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"transitions_limit","in":"query","description":"Max page transitions to return (default: 50, max: 200)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"min_views_for_dropoff","in":"query","description":"Minimum views for drop-off analysis (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved page flow analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageFlowResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-hourly-sessions":{"get":{"tags":["Analytics"],"operationId":"get_page_hourly_sessions","parameters":[{"name":"page_path","in":"query","description":"The page path to get sessions for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval: 'hour', 'day', 'week', or 'month' (default: auto-determined based on range)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved page sessions with time buckets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageHourlySessionsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-path-detail":{"get":{"tags":["Analytics"],"summary":"Get detailed analytics for a specific page path\nReturns visitors, page views, activity over time, geographic distribution, and referrers","operationId":"get_page_path_detail","parameters":[{"name":"page_path","in":"query","description":"The page path to get details for (URL-encoded)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto based on date range)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved page path detail analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathDetailResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-path-visitors":{"get":{"tags":["Analytics"],"summary":"Get individual visitor sessions for a specific page path","operationId":"get_page_path_visitors","parameters":[{"name":"page_path","in":"query","description":"The page path to get visitors for (URL-encoded)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved page path visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathVisitorsResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-paths":{"get":{"tags":["Analytics"],"operationId":"get_page_paths","parameters":[{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS (optional)","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS (optional)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of page paths to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved page paths","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-paths-sparklines":{"get":{"tags":["Analytics"],"operationId":"get_page_paths_sparklines","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"page_paths","in":"query","description":"Comma-separated list of page paths","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sparkline data for all requested page paths","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathsSparklineResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/recent-activity":{"get":{"tags":["Analytics"],"summary":"Get recent activity events for real-time activity feed","operationId":"get_recent_activity","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"since_id","in":"query","description":"Return events with ID greater than this (cursor-based polling)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","description":"Max events to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved recent activity events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecentActivityResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}":{"get":{"tags":["Analytics"],"summary":"Get detailed information about a specific session including events and request logs","operationId":"get_session_details","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDetails"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}/events":{"get":{"tags":["Analytics"],"operationId":"get_analytics_session_events","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of results to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of results to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionEventsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}/logs":{"get":{"tags":["Analytics"],"operationId":"get_session_logs","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of results to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of results to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionLogsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitor-facets":{"get":{"tags":["Analytics"],"summary":"Get filter dropdown contents for the visitors page. Returns the top\nvalues per dimension with distinct visitor counts so the UI can render\n\"Country — 1,234 visitors\" rows. Each dimension is computed against the\nsegment minus its own filter, so a selected value never collapses its\nown dropdown.","operationId":"get_visitor_facets","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_crawlers","in":"query","description":"Include crawlers (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"has_activity_only","in":"query","description":"Hide ghost visitors (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"per_facet_limit","in":"query","description":"Top N values per dimension (default: 50, max: 200)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"filter_country","in":"query","description":"Geolocation country","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Geolocation region","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Geolocation city","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"First-touch channel","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"First-touch referrer hostname (use 'Direct' for null)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Top values per dimension","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorFacets"}}}},"400":{"description":"Invalid date format or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors":{"get":{"tags":["Analytics"],"summary":"Get list of visitors with summary information","operationId":"get_visitors","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_crawlers","in":"query","description":"Include crawlers (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"limit","in":"query","description":"Maximum number of visitors to return (default: 50)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of visitors to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"has_activity_only","in":"query","description":"Filter to only include visitors with recorded activity (events/sessions). When true, excludes ghost visitors (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"filter_country","in":"query","description":"Geolocation country","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Geolocation region","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Geolocation city","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"First-touch channel","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"First-touch referrer hostname (use 'Direct' for null)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorsResponse"}}}},"400":{"description":"Invalid date format, missing required parameters, or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/guid/{visitor_id}":{"get":{"tags":["Analytics"],"summary":"Get visitor by GUID with geolocation data","operationId":"get_visitor_by_guid","parameters":[{"name":"visitor_id","in":"path","description":"Visitor GUID (supports enc_ prefix for encrypted IDs)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor with geolocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorWithGeolocation"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/id/{id}":{"get":{"tags":["Analytics"],"summary":"Get visitor by numeric ID with geolocation data","operationId":"get_visitor_by_id","parameters":[{"name":"id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor with geolocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorWithGeolocation"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}":{"get":{"tags":["Analytics"],"summary":"Get detailed information about a specific visitor by numeric ID","operationId":"get_visitor_details","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorDetails"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/enrich":{"put":{"tags":["Analytics"],"operationId":"enrich_visitor","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID - can be numeric ID, GUID, or encrypted GUID (enc_xxx)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichVisitorRequest"}}},"required":true},"responses":{"200":{"description":"Successfully enriched visitor data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichVisitorResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/info":{"get":{"tags":["Analytics"],"summary":"Get visitor record from database","operationId":"get_visitor_info","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorRecord"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/journey":{"get":{"tags":["Analytics"],"summary":"Get the complete visitor journey: all events across all sessions, grouped by session","operationId":"get_visitor_journey","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit_sessions","in":"query","description":"Maximum number of sessions to return (default: 50)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor journey","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorJourneyResponse"}}}},"400":{"description":"Invalid parameters"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/sessions":{"get":{"tags":["Analytics"],"summary":"Get all sessions for a specific visitor by numeric ID","operationId":"get_analytics_visitor_sessions","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of sessions to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor sessions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorSessionsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/stats":{"get":{"tags":["Analytics"],"summary":"Get visitor statistics","operationId":"get_visitor_stats","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorStats"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys":{"get":{"tags":["API Keys"],"operationId":"list_api_keys","parameters":[{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"API keys retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["API Keys"],"operationId":"create_api_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}},"required":true},"responses":{"201":{"description":"API key created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"409":{"description":"Conflict - API key name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/permissions":{"get":{"tags":["API Keys"],"operationId":"get_api_key_permissions","responses":{"200":{"description":"Available permissions and roles retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailablePermissions"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}":{"get":{"tags":["API Keys"],"operationId":"get_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["API Keys"],"operationId":"update_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"API key updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"409":{"description":"Conflict - API key name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["API Keys"],"operationId":"delete_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"API key deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/activate":{"post":{"tags":["API Keys"],"operationId":"activate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key activated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/deactivate":{"post":{"tags":["API Keys"],"operationId":"deactivate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key deactivated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/rotate":{"post":{"tags":["API Keys"],"operationId":"rotate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key rotated successfully; the response contains the new plaintext secret, shown only once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/auth/cli/device/approve":{"post":{"tags":["Authentication"],"operationId":"cli_device_approve","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveRequest"}}},"required":true},"responses":{"200":{"description":"Session approved; CLI can now claim the API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Unknown user_code"},"409":{"description":"Already resolved"},"410":{"description":"Session expired"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/deny":{"post":{"tags":["Authentication"],"operationId":"cli_device_deny","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveRequest"}}},"required":true},"responses":{"200":{"description":"Session denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Unknown user_code"},"409":{"description":"Already resolved"},"410":{"description":"Session expired"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/lookup":{"get":{"tags":["Authentication"],"operationId":"cli_device_lookup","parameters":[{"name":"user_code","in":"query","description":"`user_code` as displayed in the CLI / pasted into the URL.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Device session metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceLookupResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Unknown user_code"},"410":{"description":"Device session expired"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/poll":{"post":{"tags":["Authentication"],"operationId":"cli_device_poll","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDevicePollRequest"}}},"required":true},"responses":{"200":{"description":"Poll result; check `status` field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDevicePollResponse"}}}},"404":{"description":"Unknown device_code"},"500":{"description":"Internal server error"}}}},"/auth/cli/device/start":{"post":{"tags":["Authentication"],"operationId":"cli_device_start","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceStartRequest"}}},"required":true},"responses":{"200":{"description":"Device session created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceStartResponse"}}}},"500":{"description":"Internal server error"}}}},"/auth/cli/logout":{"post":{"tags":["Authentication"],"operationId":"cli_logout","responses":{"204":{"description":"API key revoked"},"401":{"description":"Not authenticated"},"403":{"description":"Endpoint requires API key authentication"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/auth/email-status":{"get":{"tags":["Authentication"],"operationId":"email_status","responses":{"200":{"description":"Email configuration status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailStatusResponse"}}}},"500":{"description":"Internal server error"}}}},"/auth/login":{"post":{"tags":["Authentication"],"operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Login successful, session cookie set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"401":{"description":"Invalid credentials, or the account's role requires MFA enrollment that has not been completed"},"500":{"description":"Internal server error"}}}},"/auth/oidc/callback":{"get":{"tags":["Authentication"],"operationId":"oidc_callback","parameters":[{"name":"code","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"state","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"error","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"error_description","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"302":{"description":"Redirect to app with session cookie or login error"}}}},"/auth/oidc/login/{slug}":{"get":{"tags":["Authentication"],"operationId":"start_oidc_login_by_slug","parameters":[{"name":"slug","in":"path","description":"OIDC provider slug (from /email-status or /auth/oidc/providers)","required":true,"schema":{"type":"string"}},{"name":"return_to","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"302":{"description":"Redirect to IdP authorize URL"},"404":{"description":"Provider not found"},"503":{"description":"OIDC provider unreachable"}}}},"/auth/oidc/providers":{"get":{"tags":["Authentication"],"operationId":"list_public_providers","responses":{"200":{"description":"Enabled OIDC providers for login page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProvidersListResponse"}}}}}}},"/auth/password-reset/request":{"post":{"tags":["Authentication"],"operationId":"request_password_reset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRequest"}}},"required":true},"responses":{"200":{"description":"Reset email sent if account exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"503":{"description":"Email service not configured"}}}},"/auth/password-reset/verify":{"post":{"tags":["Authentication"],"operationId":"reset_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Password reset successful","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Invalid or expired token"},"500":{"description":"Internal server error"}}}},"/auth/verify-email":{"get":{"tags":["Authentication"],"operationId":"verify_email","parameters":[{"name":"token","in":"query","description":"Email verification token","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email verified successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Invalid or expired token"},"500":{"description":"Internal server error"}}}},"/auth/verify-mfa":{"post":{"tags":["Authentication"],"operationId":"verify_mfa_challenge","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerificationRequest"}}},"required":true},"responses":{"204":{"description":"MFA verification successful"},"400":{"description":"Invalid request"},"401":{"description":"Invalid MFA code"},"500":{"description":"Internal server error"}}}},"/backups/alerts":{"get":{"tags":["Backups"],"summary":"List open backup alerts.","description":"Returns all alerts that have not yet been resolved, ordered by `opened_at`\ndescending (newest first). The UI renders these as a banner above the\nBackups page content. Alerts are auto-opened by the watcher and\nauto-resolved when the triggering condition clears.\n\n**Schedule overdue** — the backup scheduler did not enqueue a job within\nthe expected window (1 hour past `next_run`). Usually means the scheduler\ntask is dead or wedged.\n\n**Job stalled** — a `backup_jobs` row has been in `state='pending'` for\nmore than 1 hour. The runner never claimed the job. Usually means the\nrunner task is dead or the runner concurrency cap is too low.","operationId":"list_backup_alerts","responses":{"200":{"description":"List of open backup alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupAlertListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/cleanup":{"post":{"tags":["Backups"],"summary":"Preview or run retention using each selected schedule's configured retention days.","operationId":"cleanup_expired_backups","parameters":[{"name":"dry_run","in":"query","description":"Return the backups selected by retention without deleting anything.","required":false,"schema":{"type":"boolean"}},{"name":"schedule_id","in":"query","description":"Limit cleanup to one backup schedule.","required":false,"schema":{"type":["integer","null"],"format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleanupExpiredBackupsRequest"}}},"required":true},"responses":{"200":{"description":"Retention cleanup completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionCleanupReport"}}}},"400":{"description":"Missing or invalid preview candidate list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule or backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Cleanup preview is stale","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Cleanup could not be started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{id}/run":{"post":{"tags":["Backups"],"summary":"Run a backup for an external service manually.","description":"Enqueues the backup for asynchronous execution via the `BackupRunner`\n(ADR-014). Returns `202 Accepted` immediately: pending parent and child\nrows are inserted, and a `backup_jobs` row is enqueued for the resolved\nengine. Poll `GET /backups/{id}` to observe `pending → running → completed`.","operationId":"run_external_service_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunExternalServiceBackupRequest"}}},"required":true},"responses":{"202":{"description":"Backup enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceBackupResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"External service or S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{service_id}/backups":{"get":{"tags":["Backups"],"summary":"List all backups for a specific external service (DB-only, no S3 scan).","description":"Returns a paginated list of backups that belong to this service.\nCompletes in <100 ms regardless of S3 endpoint latency because it\nnever touches S3.","operationId":"list_external_service_backups","parameters":[{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based). Defaults to 1.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"page_size","in":"query","description":"Items per page. Defaults to 20, max 100.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Paginated list of backups for this service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceBackupListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{service_id}/schedules":{"get":{"tags":["Backups"],"summary":"List the schedules that target a specific external service. Useful for\nthe service detail page (\"which schedules back this DB up?\").","operationId":"list_service_schedules","parameters":[{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Schedules backing up this service","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources":{"get":{"tags":["Backups"],"summary":"List all S3 sources","operationId":"list_s3_sources","responses":{"200":{"description":"List of S3 sources","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/S3SourceResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Create a new S3 source","operationId":"create_s3_source","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateS3SourceRequest"}}},"required":true},"responses":{"201":{"description":"S3 source created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/test":{"post":{"tags":["Backups"],"summary":"Test S3 connectivity against a prospective source configuration (before creating it).\nThe credentials are NOT persisted. Useful for validating the form in the UI.","operationId":"test_s3_connection_preview","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateS3SourceRequest"}}},"required":true},"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3ConnectionTestResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}":{"get":{"tags":["Backups"],"summary":"Get an S3 source by ID","operationId":"get_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 source details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Delete an S3 source","operationId":"delete_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"S3 source deleted"},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Backups"],"summary":"Update an S3 source","operationId":"update_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateS3SourceRequest"}}},"required":true},"responses":{"200":{"description":"S3 source updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/backups":{"get":{"tags":["Backups"],"summary":"List all backups in an S3 source","operationId":"list_source_backups","parameters":[{"name":"include_s3_scan","in":"query","description":"When `true`, scan the S3 bucket for backups not tracked in the\nlocal database (useful after disaster-recovery from another Temps\ninstance). Defaults to `false` — the fast DB-only path.","required":false,"schema":{"type":"boolean"}},{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of all backups in the source","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceBackupIndexResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/run":{"post":{"tags":["Backups"],"summary":"Run a backup immediately for an S3 source.","description":"Enqueues the backup for asynchronous execution via the `BackupRunner`\n(ADR-014). Returns `202 Accepted` immediately: a `backups` row is inserted\nwith `state='pending'` and a `backup_jobs` row is enqueued for the\n`ControlPlaneEngine`. Poll `GET /backups/{id}` to observe\n`pending → running → completed`.","operationId":"run_backup_for_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunBackupRequest"}}},"required":true},"responses":{"202":{"description":"Backup enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/set-default":{"post":{"tags":["Backups"],"summary":"Mark an S3 source as the default. All new backups/schedules/services that do not\nexplicitly reference a source will use the default. Returns the updated source.","operationId":"set_default_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 source marked as default","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/test":{"post":{"tags":["Backups"],"summary":"Test connectivity to an existing S3 source using its stored credentials.","operationId":"test_s3_source_connection","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3ConnectionTestResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedule-runs/{id}/cancel":{"post":{"tags":["Backups"],"summary":"Cancel every non-terminal child backup belonging to a schedule run.","description":"Loops over `state IN ('pending','running')` children and flips each via\nthe same path as the per-backup cancel endpoint. The parent\n`schedule_runs.finished_at` is stamped automatically once no live\nchildren remain. Idempotent: cancelling a run with no live children is\na 200 with `cancelled = 0`.","operationId":"cancel_schedule_run","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Cancel processed (idempotent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedule-runs/{id}/jobs":{"get":{"tags":["Backups"],"summary":"List the individual backup jobs for a single scheduler run.","description":"Returns each child `backups` row joined with its external service name and\nthe most-recent `backup_jobs` engine key. Used by the schedule detail\naccordion to show per-job detail on row expand.\n\n`page_size` defaults to 50 and is capped at 200.","operationId":"list_schedule_run_jobs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Jobs for this scheduler run","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunJobEntry"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules":{"get":{"tags":["Backups"],"summary":"List all backup schedules","operationId":"list_backup_schedules","responses":{"200":{"description":"List of backup schedules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Create a new backup schedule","operationId":"create_backup_schedule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBackupScheduleRequest"}}},"required":true},"responses":{"201":{"description":"Backup schedule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}":{"get":{"tags":["Backups"],"summary":"Get a backup schedule by ID","operationId":"get_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Delete a backup schedule","operationId":"delete_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Backup schedule deleted"},"404":{"description":"Backup schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Backups"],"summary":"Update a backup schedule (partial update).","description":"All request fields are optional; only fields that are present in the\nJSON body are updated. Absent fields leave the corresponding column\nunchanged. If `schedule_expression` is changed, `next_run` is\nrecomputed automatically.","operationId":"update_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBackupScheduleRequest"}}},"required":true},"responses":{"200":{"description":"Schedule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/backups":{"get":{"tags":["Backups"],"summary":"List backups for a schedule","operationId":"list_backups_for_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of backups for the schedule","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupResponse"}}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/disable":{"patch":{"tags":["Backups"],"summary":"Disable a backup schedule","operationId":"disable_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/enable":{"patch":{"tags":["Backups"],"summary":"Enable a backup schedule","operationId":"enable_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/run":{"post":{"tags":["Backups"],"summary":"Immediately fan-out a run for the given schedule (Run Now).","description":"Creates one `schedule_runs` row, one control-plane backup job, and one\nbackup job per supported external service — all in a single transaction.\nReturns `202 Accepted` with a [`ScheduleRunResponse`] containing the new\n`schedule_run_id` and the list of enqueued jobs. Returns `409 Conflict` if\na run for this schedule is already in flight or if the schedule is disabled.","operationId":"run_schedule_now","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Fan-out run enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleRunResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Run already in flight or schedule disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/runs":{"get":{"tags":["Backups"],"summary":"Paginated run history for a backup schedule (one row per scheduler tick).","description":"Returns one [`ScheduleRunSummary`] per scheduler tick, with child backup\ncounts aggregated in a single SQL round-trip. Legacy `backups` rows (pre-\nfan-out) are surfaced as synthetic single-job runs so history does not\ndisappear. Ordered by `started_at DESC` (newest first).\n\nUse `GET /backups/schedule-runs/{run_id}/jobs` to drill into a single run.","operationId":"list_schedule_runs","parameters":[{"name":"page","in":"query","description":"Page number (1-based, defaults to 1, clamped to 1 if < 1).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"page_size","in":"query","description":"Items per page (defaults to 20, clamped to 100 if > 100).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Paginated run history for the schedule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleRunSummaryList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/services":{"get":{"tags":["Backups"],"summary":"List the external services attached to a backup schedule.","operationId":"list_schedule_services","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Services attached to this schedule","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExternalServiceSummary"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Attach one or more external services to a backup schedule. Idempotent —\nservices that are already attached are silently skipped (`ON CONFLICT\nDO NOTHING`). Returns the count of newly inserted rows + the total\nmembership after the operation.","operationId":"attach_schedule_services","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachScheduleServicesRequest"}}},"required":true},"responses":{"200":{"description":"Services attached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachScheduleServicesResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/services/{service_id}":{"delete":{"tags":["Backups"],"summary":"Detach a single external service from a backup schedule. Idempotent —\nreturns `204` whether or not a row was actually removed.","operationId":"detach_schedule_service","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service detached (or was not attached)"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}":{"get":{"tags":["Backups"],"summary":"Get a backup by ID","operationId":"get_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Backup details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Permanently delete one terminal backup from object storage and the database.","operationId":"delete_backup","parameters":[{"name":"id","in":"path","description":"Backup UUID","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Backup deleted"},"400":{"description":"Backup artifact cannot be safely attributed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Backup is running, referenced, or lacks safe artifact identity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Object storage or database error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}/cancel":{"post":{"tags":["Backups"],"summary":"Cancel a single in-flight backup.","description":"Flips the parent `backups` row + its latest `backup_jobs` row to\n`failed` with reason `\"cancelled by user \"`. The in-process\n`CancellationToken` is observed on the next heartbeat tick (≤5s), so the\nengine exits cleanly and rollback reaps the sidecar. Idempotent: cancelling\nan already-terminal backup is a 200 with `cancelled = 0`.","operationId":"cancel_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cancel processed (idempotent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}/children":{"get":{"tags":["Backups"],"summary":"List the external-service child backups that belong to a parent backup.","description":"Each entry in `children` corresponds to one `external_service_backups` row,\njoined with `external_services` so the caller receives the service name and\ntype without a second request.\n\nReturns an empty `{ \"children\": [] }` — **not 404** — when the parent\nbackup exists but has no children (e.g. control-plane backups).\nReturns 404 when the parent backup itself does not exist.","operationId":"list_backup_children","parameters":[{"name":"id","in":"path","description":"Integer row id of the parent backup","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Child backup list (may be empty)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChildBackupListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Parent backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob":{"get":{"tags":["Blob"],"summary":"List blobs","operationId":"blob_list","parameters":[{"name":"limit","in":"query","description":"Maximum number of items to return","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"prefix","in":"query","description":"Prefix to filter by","required":false,"schema":{"type":"string"}},{"name":"cursor","in":"query","description":"Continuation token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of blobs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBlobsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Blob"],"summary":"Upload a blob","operationId":"blob_put","requestBody":{"description":"Binary blob data","content":{"application/octet-stream":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"Blob uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Blob"],"summary":"Delete blobs","operationId":"blob_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blobs deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteBlobResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob/copy":{"post":{"tags":["Blob"],"summary":"Copy a blob to a new location","operationId":"blob_copy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopyBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob copied successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Source blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob/disable":{"delete":{"tags":["Blob Management"],"summary":"Disable Blob service","operationId":"blob_disable","responses":{"200":{"description":"Blob service disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableBlobResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Blob service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/enable":{"post":{"tags":["Blob Management"],"summary":"Enable Blob service","operationId":"blob_enable","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob service enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableBlobResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/status":{"get":{"tags":["Blob Management"],"summary":"Get Blob service status","operationId":"blob_status","responses":{"200":{"description":"Blob service status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/update":{"patch":{"tags":["Blob Management"],"summary":"Update Blob service configuration","operationId":"blob_update","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob service updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBlobResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Blob service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/{project_id}/{path}":{"get":{"tags":["Blob"],"summary":"Download a blob","operationId":"blob_download","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","description":"Blob path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Blob content"},"404":{"description":"Blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"head":{"tags":["Blob"],"summary":"Get blob metadata","operationId":"blob_head","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","description":"Blob path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Blob metadata in headers"},"404":{"description":"Blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/dashboard/projects-analytics":{"get":{"tags":["Events"],"summary":"Get dashboard analytics for multiple projects in a single batch request","description":"Returns unique visitor counts and hourly sparkline data for all requested projects\nusing only 2 SQL queries instead of 2×N per-project queries.","operationId":"get_dashboard_projects_analytics","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date for filtering","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved batch analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardProjectsAnalyticsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/activity-graph":{"get":{"tags":["Deployments"],"summary":"Get deployment activity graph showing daily deployment counts\nSimilar to GitHub's contribution graph","operationId":"get_activity_graph","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"days","in":"query","description":"Number of days to include (default: 365)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved activity graph","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityGraphResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/{deployment_id}/vulnerability-scan":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan_by_deployment","parameters":[{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Scan for the specified deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"No scan found for deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on a deployment.","operationId":"DeploymentMetricsGetRange","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics/enable":{"patch":{"tags":["Metrics"],"summary":"Enable or disable OTLP metric ingestion for a deployment.","description":"When `enabled=true`, seeds the default container alert rules for the\ndeployment via [`temps_monitoring::seed_default_container_rules`] (idempotent).","operationId":"DeploymentMetricsToggle","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleDeploymentMetricsRequest"}}},"required":true},"responses":{"200":{"description":"Metrics toggle applied"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics/latest":{"get":{"tags":["Metrics"],"summary":"Fetch the most-recent metric values for a deployment.","operationId":"DeploymentMetricsGetLatest","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of metric name to latest value","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/dns-providers":{"get":{"tags":["DNS Providers"],"summary":"List all DNS providers","operationId":"list_dns_providers","responses":{"200":{"description":"List of DNS providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DnsProviderResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["DNS Providers"],"summary":"Create a new DNS provider","description":"The provider's credentials will be tested before creation.\nIf the connection test fails, the provider will not be created.","operationId":"create_dns_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDnsProviderRequest"}}},"required":true},"responses":{"201":{"description":"DNS provider created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"400":{"description":"Invalid request or connection test failed"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}":{"get":{"tags":["DNS Providers"],"summary":"Get a DNS provider by ID","operationId":"get_dns_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"DNS provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["DNS Providers"],"summary":"Update a DNS provider","description":"If new credentials are supplied, they are tested before the update is\npersisted (same as creation) -- otherwise a provider's credentials (and,\nfor Pebble, its target URL) could be swapped for something invalid or\nunsafe without ever going through validation.","operationId":"update_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDnsProviderRequest"}}},"required":true},"responses":{"200":{"description":"DNS provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["DNS Providers"],"summary":"Delete a DNS provider","operationId":"delete_dns_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"DNS provider deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/domains":{"get":{"tags":["DNS Providers"],"summary":"List managed domains for a provider","operationId":"list_managed_domains","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of managed domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["DNS Providers"],"summary":"Add a managed domain to a provider","operationId":"add_managed_domain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddManagedDomainApiRequest"}}},"required":true},"responses":{"201":{"description":"Managed domain added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/test":{"post":{"tags":["DNS Providers"],"summary":"Test provider connection","operationId":"test_provider_connection","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionTestResult"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/zones":{"get":{"tags":["DNS Providers"],"summary":"List zones available in a provider","operationId":"list_provider_zones","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of zones","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZoneListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}":{"delete":{"tags":["DNS Providers"],"summary":"Remove a managed domain","operationId":"remove_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Managed domain removed"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["DNS Providers"],"summary":"Update a managed domain's settings (hostname mode, sync opt-in, auto-manage).","operationId":"update_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateManagedDomainApiRequest"}}},"required":true},"responses":{"200":{"description":"Managed domain updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/apply-hostname-mode":{"post":{"tags":["DNS Providers"],"summary":"Apply a hostname mode to a managed domain (persist + optional DNS sync +\nroute reload).","operationId":"apply_hostname_mode","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyHostnameModeRequest"}}},"required":true},"responses":{"200":{"description":"Hostname mode applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostnamePreviewResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions or token lacks zone access"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/hostname-preview":{"get":{"tags":["DNS Providers"],"summary":"Preview the impact of switching a managed domain's hostname mode.","operationId":"preview_hostname_mode","parameters":[{"name":"mode","in":"query","description":"Target mode: standard|flat","required":true,"schema":{"type":"string"}},{"name":"sync","in":"query","description":"Include DNS record changes","required":false,"schema":{"type":"boolean"}},{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Hostname mode preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostnamePreviewResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/verify":{"post":{"tags":["DNS Providers"],"summary":"Verify a managed domain","operationId":"verify_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Domain verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns/lookup":{"get":{"tags":["DNS"],"summary":"Lookup DNS A records for a domain","operationId":"lookup_dns_a_records","parameters":[{"name":"domain","in":"query","description":"Domain name to lookup","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved DNS A records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupResponse"}}}},"400":{"description":"Invalid domain name or lookup failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupError"}}}}}}},"/domains":{"get":{"tags":["Domains"],"summary":"List all domains","operationId":"list_domains","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"search","in":"query","description":"Search domains by name (substring match)","required":false,"schema":{"type":["string","null"]},"example":"example.com"}],"responses":{"200":{"description":"Domains retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDomainsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Domains"],"summary":"Create a new domain","description":"Creates a new domain and automatically requests a Let's Encrypt challenge.\nYou can specify the challenge type (HTTP-01 or DNS-01) in the request.\n\n- **HTTP-01**: Validates domain ownership by placing a file on your web server at `/.well-known/acme-challenge/`\n- **DNS-01**: Validates domain ownership by adding a TXT record to your DNS (required for wildcard domains)","operationId":"create_domain","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/by-host/{hostname}":{"get":{"tags":["Domains"],"summary":"Get domain details by hostname","operationId":"get_domain_by_host","parameters":[{"name":"hostname","in":"path","description":"Domain hostname","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Domain details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/by-host/{hostname}/cert-status":{"get":{"tags":["Domains"],"summary":"Get on-demand TLS certificate status for a hostname","description":"Returns the current cert lifecycle state for a single hostname (from the\n`domains` row) plus the most recent on-demand issuance attempt (from the\n`on_demand_cert_attempts` audit log). This is the operator's first-line\ndiagnostic, surfaced by `temps domain cert-status` (ADR-018 §5). Returns the\nhostname with `None` fields when no on-demand activity exists for it (never a\n404, so the CLI can render \"no attempts recorded\").","operationId":"get_on_demand_cert_status","parameters":[{"name":"hostname","in":"path","description":"Domain hostname","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"On-demand cert status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/on-demand-certs":{"get":{"tags":["Domains"],"summary":"List on-demand TLS certificate attempts","description":"Returns rows from the append-only `on_demand_cert_attempts` audit log\n(ADR-018 §5), newest first, each joined with the current authoritative cert\nstate (`status`, `expiration_time`, `backoff_until`) from the `domains` row.\nThis backs the console \"Certificates\" surface. No certificate or private-key\nmaterial is returned — only audit metadata.","operationId":"list_on_demand_certs","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20}],"responses":{"200":{"description":"On-demand cert attempts retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOnDemandCertsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/order":{"get":{"tags":["Domains"],"summary":"Get ACME order for a domain","operationId":"get_domain_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcmeOrderResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Order not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Domains"],"summary":"Create or recreate ACME order for a domain","description":"Creates a new ACME order with Let's Encrypt for the specified domain.\nIf an order already exists, you should cancel it first using the cancel-order endpoint.\nReturns the challenge details that need to be fulfilled (DNS record or HTTP token).","operationId":"create_or_recreate_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainChallengeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Domains"],"summary":"Cancel ACME order for a domain","description":"Cancels the current ACME order for a domain and clears all challenge data.\nThis allows you to start over with a new order if the previous one failed or got stuck.","operationId":"cancel_domain_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order cancelled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/order/finalize":{"post":{"tags":["Domains"],"summary":"Finalize ACME order for a domain","description":"Finalizes the ACME order by completing the challenge validation and requesting the certificate.\nThis should be called after the challenge has been set up (DNS record added or HTTP token served).","operationId":"finalize_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order finalized successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain or order not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/setup-dns":{"post":{"tags":["Domains"],"summary":"Setup DNS challenge records automatically using a DNS provider","description":"This endpoint automatically creates the required DNS TXT records for ACME DNS-01 challenge\nvalidation using a configured DNS provider. The domain must have an active DNS challenge\npending (created via POST /domains/{id}/order with dns-01 challenge type).\n\nThis is similar to how email domain DNS records are auto-provisioned.","operationId":"setup_dns_challenge","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsChallengeRequest"}}},"required":true},"responses":{"200":{"description":"DNS records created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsChallengeResponse"}}}},"400":{"description":"Bad request - DNS provider not configured or no challenge pending"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain or DNS provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}":{"get":{"tags":["Domains"],"summary":"Get domain by ID","operationId":"get_domain_by_id","parameters":[{"name":"domain","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Domains"],"summary":"Delete a domain","operationId":"delete_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Domain deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/challenge-token":{"get":{"tags":["Domains"],"summary":"Get challenge token for a domain (returns plain text token)","operationId":"get_challenge_token","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Challenge token retrieved successfully","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Challenge not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/http-challenge-debug":{"get":{"tags":["Domains"],"summary":"Get HTTP challenge debug information","description":"Returns detailed debug information for HTTP-01 challenge including:\n- Whether a challenge exists for the domain\n- The challenge token and URL that Let's Encrypt will access\n- DNS resolution information showing where the domain currently points\n\nThis is useful for debugging why HTTP-01 challenges fail.","operationId":"get_http_challenge_debug","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Debug information retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpChallengeDebugResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/provision":{"post":{"tags":["Domains"],"summary":"Provision a domain certificate","operationId":"provision_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Certificate provisioning initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/renew":{"post":{"tags":["Domains"],"summary":"Renew domain certificate","description":"For HTTP-01 domains: Automatically renews the certificate\nFor DNS-01 domains (wildcards): Creates a new ACME order and returns challenge data","operationId":"renew_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Certificate renewal initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionResponse"}}}},"202":{"description":"DNS challenge created - manual action required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainChallengeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/status":{"get":{"tags":["Domains"],"summary":"Check domain status","operationId":"check_domain_status","parameters":[{"name":"domain","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains":{"get":{"tags":["Email Domains"],"summary":"List all email domains","operationId":"list_email_domains","parameters":[{"name":"provider_id","in":"query","description":"Only return domains belonging to this provider","required":false,"schema":{"type":["integer","null"],"format":"int32"}}],"responses":{"200":{"description":"List of email domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailDomainResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Email Domains"],"summary":"Create a new email domain","operationId":"create_email_domain","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/by-domain/{domain}":{"get":{"tags":["Email Domains"],"summary":"Get an email domain by domain name with DNS records","operationId":"get_domain_by_name","parameters":[{"name":"domain","in":"path","description":"Domain name (e.g., 'mail.example.com')","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email domain details with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}":{"get":{"tags":["Email Domains"],"summary":"Get an email domain by ID with DNS records","operationId":"get_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email domain details with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Email Domains"],"summary":"Delete an email domain","operationId":"delete_email_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Domain deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/dns-records":{"get":{"tags":["Email Domains"],"summary":"Get DNS records for an email domain","operationId":"get_domain_dns_records","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"DNS records for the domain","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/setup-dns":{"post":{"tags":["Email Domains"],"summary":"Setup DNS records for an email domain using a configured DNS provider","operationId":"setup_dns","parameters":[{"name":"id","in":"path","description":"Email Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsRequest"}}},"required":true},"responses":{"200":{"description":"DNS records setup result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsResponse"}}}},"400":{"description":"Invalid request or DNS provider not configured"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/verify":{"post":{"tags":["Email Domains"],"summary":"Verify an email domain's DNS configuration","operationId":"verify_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain verification result with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers":{"get":{"tags":["Email Providers"],"summary":"List all email providers","operationId":"list_email_providers","responses":{"200":{"description":"List of email providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailProviderResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Email Providers"],"summary":"Create a new email provider","operationId":"create_email_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailProviderRequest"}}},"required":true},"responses":{"201":{"description":"Provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}":{"get":{"tags":["Email Providers"],"summary":"Get an email provider by ID","operationId":"get_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Email Providers"],"summary":"Delete an email provider","operationId":"delete_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Email Providers"],"summary":"Update an email provider","description":"Partial update — any field left out keeps its current value. Most importantly,\nomitting the credential block (`ses_credentials`/`scaleway_credentials`/`smtp_credentials`)\npreserves the stored secret, so operators can rename a provider without re-typing\npasswords. `provider_type` is immutable; to switch providers, delete and recreate.","operationId":"update_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailProviderRequest"}}},"required":true},"responses":{"200":{"description":"Provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"409":{"description":"Provider type mismatch"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/test":{"post":{"tags":["Email Providers"],"summary":"Test an email provider by sending a test email to the logged-in user","operationId":"test_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEmailRequest"}}},"required":true},"responses":{"200":{"description":"Test email result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEmailResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/tracking/setup":{"post":{"tags":["Email Providers"],"summary":"One-click AWS-side setup of SES event tracking (SNS topic + webhook\nsubscription + SESv2 event destination), using the provider's stored\ncredentials.","operationId":"setup_email_tracking","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Setup completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingSetupResponse"}}}},"400":{"description":"Provider does not support event tracking"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"502":{"description":"An AWS call failed — the response detail names the failed step"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/tracking/status":{"get":{"tags":["Email Providers"],"summary":"Live status of SES event tracking for a provider","operationId":"get_email_tracking_status","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Event tracking status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/emails":{"get":{"tags":["Emails"],"summary":"List emails with optional filtering","operationId":"list_emails","parameters":[{"name":"domain_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"project_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"status","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"from_address","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"page","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"List of emails","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEmailsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Emails"],"summary":"Send an email","operationId":"send_email","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailRequestBody"}}},"required":true},"responses":{"201":{"description":"Email sent successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailResponseBody"}}}},"400":{"description":"Invalid request or domain not verified"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/events":{"get":{"tags":["Email Tracking"],"summary":"GET /emails/events","operationId":"get_global_events","parameters":[{"name":"event_type","in":"query","description":"Filter by event type (open, click)","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated tracking events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEventsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/emails/events/stats":{"get":{"tags":["Email Tracking"],"summary":"GET /emails/events/stats","operationId":"get_global_event_stats","responses":{"200":{"description":"Global tracking statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalEventStatsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/emails/stats":{"get":{"tags":["Emails"],"summary":"Get email statistics","operationId":"get_email_stats","parameters":[{"name":"domain_id","in":"query","description":"Optional domain ID to filter stats","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailStatsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/validate":{"post":{"tags":["Email Validation"],"summary":"Validate an email address","operationId":"validate_email","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateEmailRequest"}}},"required":true},"responses":{"200":{"description":"Email validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateEmailResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/{email_id}/track/click/{link_index}":{"get":{"tags":["Email Tracking"],"summary":"Track email link click - redirects to original URL","description":"This endpoint replaces original links in tracked emails.\nNo authentication required - it's called when the recipient clicks a link.","operationId":"track_click","parameters":[{"name":"email_id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}},{"name":"link_index","in":"path","description":"Link index","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"302":{"description":"Redirect to original URL"},"404":{"description":"Link not found"}}}},"/emails/{email_id}/track/open":{"get":{"tags":["Email Tracking"],"summary":"Track email open - returns a 1x1 transparent GIF","description":"This endpoint is embedded as an tag in emails.\nNo authentication required - it's called by the email client.","operationId":"track_open","parameters":[{"name":"email_id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"1x1 transparent tracking pixel"},"404":{"description":"Email not found"}}}},"/emails/{id}":{"get":{"tags":["Emails"],"summary":"Get an email by ID","operationId":"get_email","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking":{"get":{"tags":["Email Tracking"],"summary":"Get email tracking summary","operationId":"get_email_tracking","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracking summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking/events":{"get":{"tags":["Email Tracking"],"summary":"Get email tracking events","operationId":"get_email_events","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}},{"name":"event_type","in":"query","description":"Filter by event type (open, click)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracking events","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrackingEventResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking/links":{"get":{"tags":["Email Tracking"],"summary":"Get tracked links for an email","operationId":"get_email_links","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracked links","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrackedLinkResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/external-services":{"get":{"tags":["External Services"],"summary":"Get all external services","operationId":"list_services","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of external services","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["External Services"],"summary":"Create new external service","operationId":"create_service","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateExternalServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}}}},"/external-services/available-containers":{"get":{"tags":["External Services"],"summary":"List available Docker containers that can be imported as services","operationId":"list_available_containers","responses":{"200":{"description":"List of available containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AvailableContainerInfo"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/by-slug/{slug}":{"get":{"tags":["External Services"],"summary":"Get external service details by slug","operationId":"get_service_by_slug","parameters":[{"name":"slug","in":"path","description":"External service slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"External service details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceDetails"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/health-status-batch":{"get":{"tags":["External Services"],"summary":"Current health status for many services at once","description":"Powers the status dot on the Storage list page. Pass a comma-separated\nlist of service IDs via `?ids=1,2,3`. Omit to get every service.","operationId":"list_service_health_statuses","parameters":[{"name":"ids","in":"query","description":"Comma-separated service IDs. Omit for all services.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Batch of current health statuses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthStatusBatchResponse"}}}},"500":{"description":"Internal server error"}}}},"/external-services/import":{"post":{"tags":["External Services"],"summary":"Import an existing Docker container as a managed external service","operationId":"import_external_service","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportExternalServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service imported successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/projects/{project_id}":{"get":{"tags":["External Services"],"summary":"List services linked to a project","operationId":"list_project_services","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of services linked to project","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/external-services/projects/{project_id}/environment":{"get":{"tags":["External Services"],"summary":"Get all environment variables for all services linked to a project","operationId":"get_project_service_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of service IDs to their environment variables","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"propertyNames":{"type":"integer","format":"int32"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/external-services/providers/metadata":{"get":{"tags":["External Services"],"summary":"Get provider metadata (display names, icons, descriptions)","operationId":"get_providers_metadata","responses":{"200":{"description":"List of provider metadata","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderMetadata"}}}}},"500":{"description":"Internal server error"}}}},"/external-services/providers/metadata/{service_type}":{"get":{"tags":["External Services"],"summary":"Get metadata for a specific provider","operationId":"get_provider_metadata","parameters":[{"name":"service_type","in":"path","description":"Service type (mongodb, postgres, redis, s3)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Provider metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderMetadata"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}}}},"/external-services/types":{"get":{"tags":["External Services"],"summary":"Get available service types","operationId":"get_service_types","responses":{"200":{"description":"List of available service types","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceTypeRoute"}}}}},"500":{"description":"Internal server error"}}}},"/external-services/types/{service_type}/parameters":{"get":{"tags":["External Services"],"summary":"Get parameter schema for a specific service type","operationId":"get_service_type_parameters","parameters":[{"name":"service_type","in":"path","description":"Service type","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Service type parameter schema"},"404":{"description":"Service type not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}":{"get":{"tags":["External Services"],"summary":"Get external service details","operationId":"get_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"External service details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceDetails"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["External Services"],"summary":"Update external service","operationId":"update_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateExternalServiceRequest"}}},"required":true},"responses":{"200":{"description":"Service updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"404":{"description":"Service not found"},"409":{"description":"A major upgrade is in progress for this service"},"500":{"description":"Internal server error"}}},"delete":{"tags":["External Services"],"summary":"Delete external service","operationId":"delete_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service deleted successfully"},"400":{"description":"Cannot delete: service is still linked to projects"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/cluster-health":{"get":{"tags":["External Services"],"summary":"Per-member health for a Postgres HA cluster.","description":"Reads pg_auto_failover's `pgautofailover.node` table from the cluster's\nmonitor (TLS, autoctl_node) and joins each member with its\n`pg_stat_replication` row from the current primary. Returns one row per\ndata member with role/state, sync state, and replay lag.\n\nReturns `200` with `monitor_error` set when the monitor is briefly\nunreachable (UI surfaces it as a banner above the table); the table\nitself is empty in that case. Returns `400` for non-cluster services.","operationId":"get_cluster_health","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Per-member cluster health report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterHealthReportResponse"}}}},"400":{"description":"Service is not a cluster"},"401":{"description":"Unauthorized"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/health-check":{"post":{"tags":["External Services"],"summary":"Run a health check for one service right now","description":"Triggers the same engine-specific probe as the background monitor, writes\na history row, updates the denormalized fields on `external_services`, and\nfires alerts on the Nth consecutive failure (so consecutive-failure state\nstays honest). Returns the fresh snapshot the UI can display immediately.","operationId":"trigger_service_health_check","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Fresh health snapshot after probing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthResponse"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"},"503":{"description":"Health monitor not running on this node"}}}},"/external-services/{id}/health-status":{"get":{"tags":["External Services"],"summary":"Persisted health status for an external service","description":"Returns the latest health probe result recorded by\n`ExternalServiceHealthMonitor`, plus recent check history for sparklines\nand a 24-hour uptime percentage. Safe to poll from the UI every 30s.","operationId":"get_service_health_status","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Max number of recent checks (default 50, max 200)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Current health + recent history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthResponse"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/members":{"post":{"tags":["External Services"],"summary":"Begin adding a single new member to a running cluster.","description":"Currently only `replica` members can be added at runtime. The\nresponse is **202 Accepted** as soon as the validation passes and\nthe placeholder `service_members` row is inserted. The actual\ncontainer provisioning + DNS registration runs in the background;\npoll `GET /external-services/{id}/members/{member_id}` to watch\n`provisioning_step` advance through the phases.","operationId":"add_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddClusterMemberRequest"}}},"required":true},"responses":{"202":{"description":"Cluster member provisioning started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceMemberInfo"}}}},"400":{"description":"Validation failed (wrong topology, status, or role)"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/members/{member_id}":{"get":{"tags":["External Services"],"summary":"Get a single cluster member's current state.","description":"Used by the add-member page to poll the row every second while the\nbackground provisioning task walks through its phases. The\n`provisioning_step` field advances through `inserting_row` →\n`provisioning_container` → `registering_dns` → `done` (or `failed`\nwith `provisioning_error` set).","operationId":"get_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cluster member details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceMemberInfo"}}}},"404":{"description":"Service or member not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["External Services"],"summary":"Remove a single member from a running cluster.","description":"Refuses to remove the monitor (singleton), the current primary\n(failover first), or any member if the cluster would drop below the\n2-data-member quorum required for HA. Stops + removes the container,\ndeletes the row, and drops the Tier-2 DNS record.","operationId":"remove_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Cluster member removed"},"400":{"description":"Validation failed (monitor, primary, or quorum violation)"},"404":{"description":"Service or member not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/members/{member_id}/promote":{"post":{"tags":["External Services"],"summary":"Promote a replica to primary by triggering a pg_auto_failover\nfailover. The monitor demotes the current primary and the chosen\nreplica transitions to primary; the role reconciler then refreshes\nthe role-aliased VIPs (≤30s).","operationId":"promote_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Promotion initiated"},"400":{"description":"Validation failed (monitor, already primary, not running, etc.)"},"404":{"description":"Service or member not found"},"500":{"description":"pg_autoctl perform promotion failed"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on an external service.","description":"Pass `percentile` to compute a histogram quantile instead of a plain\ngauge/counter average.","operationId":"ExternalServiceMetricsGetRange","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/alert-rules":{"get":{"tags":["Metrics"],"summary":"List all monitoring alert rules for an external service.","operationId":"ExternalServiceMetricsGetAlertRules","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of alert rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Metrics"],"summary":"Create a monitoring alert rule for an external service.","description":"If metric collection is enabled and the service engine has default rules,\nseeding is idempotent (ON CONFLICT DO NOTHING).","operationId":"ExternalServiceMetricsCreateAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceCreateAlertRuleRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/alert-rules/{rule_id}":{"put":{"tags":["Metrics"],"summary":"Update an existing monitoring alert rule for an external service.","operationId":"ExternalServiceMetricsUpdateAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUpdateAlertRuleRequest"}}},"required":true},"responses":{"200":{"description":"Updated alert rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Metrics"],"summary":"Delete a monitoring alert rule for an external service.","operationId":"ExternalServiceMetricsDeleteAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/by-database":{"get":{"tags":["Metrics"],"summary":"Return the latest per-database metric values for a Postgres service.","description":"Groups `pg_stat_database` / size metrics by `datname` so the UI can show a\nbreakdown table (each database with its own size, cache-hit ratio, etc.)\nrather than collapsing every database into one value.","operationId":"ExternalServiceMetricsByDatabase","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Per-database metric breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMetricsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/enable":{"patch":{"tags":["Metrics"],"summary":"Enable or disable metric collection for an external service.","description":"When `enabled=true`, seeds the default alert rules for the service's engine\nvia [`temps_monitoring::seed_default_rules`] (idempotent).","operationId":"ExternalServiceMetricsToggle","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleServiceMetricsRequest"}}},"required":true},"responses":{"200":{"description":"Metrics toggle applied"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/latest":{"get":{"tags":["Metrics"],"summary":"Fetch the most-recent value for every tracked metric on an external service.","operationId":"ExternalServiceMetricsGetLatest","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of metric name to latest value","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/status":{"get":{"tags":["Metrics"],"summary":"Return the freshness status (last-received timestamp) for a service.","description":"Cheap O(1) lookup against `service_metrics_status` — used by the UI to show\n\"last received at …\" without scanning the metrics hypertable.","operationId":"ExternalServiceMetricsStatus","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Metrics freshness status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsStatusResponse"}}}},"503":{"description":"Metrics not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/parameters/{param_name}":{"get":{"tags":["External Services"],"summary":"Reveal one sensitive service parameter. Service detail responses never\ncontain plaintext values; every successful reveal is recorded separately.","operationId":"reveal_service_parameter","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"param_name","in":"path","description":"Sensitive parameter name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sensitive parameter value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveValueResponse"}}}},"400":{"description":"Parameter is not sensitive"},"403":{"description":"Caller cannot access a project linked to this service"},"404":{"description":"Service or parameter not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/preview-environment-masked":{"get":{"tags":["External Services"],"summary":"Get environment variables preview with masked sensitive values","operationId":"get_service_preview_environment_variables_masked","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Preview of environment variables with sensitive values masked as ***","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/preview-environment-names":{"get":{"tags":["External Services"],"summary":"Get environment variable names preview (safe - no sensitive values)","operationId":"get_service_preview_environment_variable_names","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variable names that would be provided","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects":{"get":{"tags":["External Services"],"summary":"List projects linked to service","operationId":"list_service_projects","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of linked projects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["External Services"],"summary":"Link service to project","operationId":"link_service_to_project","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service linked to project successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}},"404":{"description":"Service or project not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}":{"delete":{"tags":["External Services"],"summary":"Unlink service from project","operationId":"unlink_service_from_project","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service unlinked from project successfully"},"404":{"description":"Service link not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}/environment":{"get":{"tags":["External Services"],"summary":"Get all environment variables for a service-project pair","operationId":"get_service_environment_variables","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariableInfo"}}}}},"404":{"description":"Service or project not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}/environment/{var_name}":{"get":{"tags":["External Services"],"summary":"Get specific environment variable for a service-project pair","operationId":"get_service_environment_variable","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_name","in":"path","description":"Environment variable name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableInfo"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Service, project, or variable not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/resources":{"patch":{"tags":["External Services"],"summary":"Update a service's resource limits (memory, CPU caps).","description":"Persists the new caps to the encrypted config AND live-applies them\nvia Docker's update API. Memory and CPU can be hot-changed without a\nrestart on running containers; stopped containers also accept the\nupdate and pick up the new caps on next start.\n\nPass `null` (or omit) any field to leave it unlimited. A request where\nevery field is `null` removes any existing limits.\n\nThe response includes a per-container `applied[]` list so the caller\ncan tell which members got the update and which were skipped (e.g.,\ncontainer not yet created, or `docker update` rejected because the\nnew memory cap is below current usage).","operationId":"update_service_resources","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResourceLimits"}}},"required":true},"responses":{"200":{"description":"Updated resource limits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceLimitsUpdateResponse"}}}},"400":{"description":"Invalid resource limits"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/restore":{"post":{"tags":["Restore"],"operationId":"start_restore","parameters":[{"name":"id","in":"path","description":"External service id (source for the restore)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRestoreRequest"}}},"required":true},"responses":{"202":{"description":"Restore run started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreRunView"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup or service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-capabilities":{"get":{"tags":["Restore"],"operationId":"get_restore_capabilities","parameters":[{"name":"id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Capabilities declared by the service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreCapabilitiesResponse"}}}},"404":{"description":"Service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-plan":{"post":{"tags":["Restore"],"operationId":"plan_restore","parameters":[{"name":"id","in":"path","description":"Target service id","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRestoreRequest"}}},"required":true},"responses":{"200":{"description":"Preview of what the restore will do","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestorePlan"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup or service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-runs":{"get":{"tags":["Restore"],"operationId":"list_restore_runs_for_service","parameters":[{"name":"id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Recent restore runs for the service","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RestoreRunView"}}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/retry":{"post":{"tags":["External Services"],"summary":"Retry a failed cluster service initialization.","description":"Cleans up any leftover containers from the previous attempt and\nre-runs cluster initialization with the provided member specifications.","operationId":"retry_cluster","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryClusterRequest"}}},"required":true},"responses":{"200":{"description":"Cluster retry initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Service is not a failed cluster"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/runtime":{"get":{"tags":["External Services"],"summary":"Inspect a service's container(s): status, restart count, OOM-killed flag,\nexit code, and the cgroup limits actually applied.","operationId":"get_service_runtime","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container runtime snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceRuntimeReport"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/start":{"post":{"tags":["External Services"],"summary":"Start an external service","operationId":"start_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Service started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"404":{"description":"Service not found"},"409":{"description":"A Postgres major upgrade is in progress for this service"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/stats":{"get":{"tags":["External Services"],"summary":"Sample current CPU/memory usage from each of a service's containers.\nOne-shot sample, no streaming. Cheap to call (single Docker round-trip\nper member) so the UI can poll on a 5–10s interval.","operationId":"get_service_stats","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container stats snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceStatsReport"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/stop":{"post":{"tags":["External Services"],"summary":"Stop an external service","operationId":"stop_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Service stopped successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/upgrade":{"post":{"tags":["External Services"],"summary":"Upgrade external service to new Docker image with data migration\nThis endpoint uses service-specific upgrade procedures (e.g., pg_upgrade for PostgreSQL)","operationId":"upgrade_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeExternalServiceRequest"}}},"required":true},"responses":{"200":{"description":"Service upgraded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request or upgrade not supported"},"404":{"description":"Service not found"},"409":{"description":"A major upgrade is already in progress for this service"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/wal-health":{"get":{"tags":["External Services"],"summary":"Postgres WAL & archive health snapshot","description":"Returns the latest WAL/archive health snapshot recorded by the background\nhealth monitor for a Postgres external service. Powers the warning banner\non the service detail page when the disk is filling up due to stale\nreplication slots, archive backlog, or misconfigured `archive_command`.\n\nReturns 404 when no snapshot exists yet (probe hasn't run, or the service\nisn't Postgres).","operationId":"getPostgresWalHealth","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest WAL health snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostgresWalHealth"}}}},"404":{"description":"Service not found, or no WAL snapshot available"},"500":{"description":"Internal server error"}}}},"/external-services/{service_id}/pg-stat-statements/enable":{"post":{"tags":["External Services"],"summary":"Enable `pg_stat_statements` on a standalone Postgres service.","description":"Stops the container and restarts it so that the\n`shared_preload_libraries=pg_stat_statements` CMD flag (baked into every\nnew standalone Postgres container) takes effect. The named data volume is\nreused unchanged — no data is lost.\n\n**Clustered (HA) services are rejected** with 422 — a blind single-container\nrestart bypasses controlled failover. For clustered services the response\nbody describes the manual rolling-restart steps.\n\nConfirmation is the caller's responsibility (UI dialog / CLI `--yes` flag)\nbefore invoking this endpoint.","operationId":"ExternalServiceEnablePgStatStatements","parameters":[{"name":"service_id","in":"path","description":"ID of the provisioned standalone Postgres service","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container restarted; pg_stat_statements now active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnablePgStatStatementsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (requires external_services:write)"},"404":{"description":"Service not found"},"422":{"description":"Service is not standalone Postgres (cluster or wrong type)"},"500":{"description":"Restart failed"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/pg-stat-statements/slow-queries":{"get":{"tags":["External Services"],"operationId":"get_slow_queries","parameters":[{"name":"service_id","in":"path","description":"ID of the provisioned Postgres service","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based). Defaults to 1.","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}},{"name":"page_size","in":"query","description":"Number of rows per page (1–100). Defaults to 20.","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}},{"name":"sort_by","in":"query","description":"Column to sort by: one of `calls`, `total_exec_time_ms`,\n`mean_exec_time_ms`, `rows`, `cache_hit_ratio`. Defaults to\n`mean_exec_time_ms`. Applied server-side so ordering stays\nconsistent across pages.","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","description":"Sort direction: `asc` or `desc`. Defaults to `desc`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Paginated slow queries from pg_stat_statements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlowQueriesResponse"}}}},"400":{"description":"Invalid pagination or sort parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (requires external_services:read)"},"404":{"description":"Service not found"},"422":{"description":"Service is not a Postgres service"},"503":{"description":"pg_stat_statements extension not available (container restart required)"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers":{"get":{"tags":["External Services - Query"],"summary":"List containers at the root level (databases, keyspaces, etc.)","operationId":"list_root_containers","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of root containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}":{"get":{"tags":["External Services - Query"],"summary":"List containers at a specific path\nPath segments are separated by forward slashes\nExample: /external-services/1/query/containers/mydb lists schemas in database \"mydb\"","operationId":"list_containers_at_path","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities":{"get":{"tags":["External Services - Query"],"summary":"List entities (tables, collections, etc.) in a container\nExample: /external-services/1/query/containers/mydb/public/entities lists tables in the public schema","operationId":"list_entities","parameters":[{"name":"limit","in":"query","description":"Maximum number of entities to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","minimum":0}},{"name":"token","in":"query","description":"Continuation token for pagination","required":false,"schema":{"type":"string"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of entities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEntitiesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}":{"get":{"tags":["External Services - Query"],"summary":"Get detailed information about an entity (table schema)","operationId":"get_entity_info","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Entity details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityInfoResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service, container, or entity not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}/data":{"post":{"tags":["External Services - Query"],"summary":"Query data from an entity with optional filters, pagination, and sorting","operationId":"query_data","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryDataRequest"}}},"required":true},"responses":{"200":{"description":"Query results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryDataResponse"}}}},"400":{"description":"Invalid query"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service, container, or entity not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}/download":{"get":{"tags":["External Services - Query"],"summary":"Download an object (S3 only) as a streaming response","operationId":"download_object","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Object data stream","content":{"application/octet-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Object not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/info":{"get":{"tags":["External Services - Query"],"summary":"Get information about a specific container","operationId":"get_container_info","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/explorer-support":{"get":{"tags":["External Services - Query"],"summary":"Check if a service supports query explorer functionality","operationId":"check_explorer_support","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Explorer support information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExplorerSupportResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades":{"get":{"tags":["Postgres Upgrades"],"summary":"List recent upgrades for a single service (newest first, page size 50).","operationId":"list_pg_upgrades","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Recent upgrades","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}}},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Postgres Upgrades"],"summary":"Start a new PostgreSQL major-version upgrade for a service.","operationId":"start_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartPgUpgradeRequest"}}},"required":true},"responses":{"201":{"description":"Upgrade started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"400":{"description":"Invalid request"},"409":{"description":"An upgrade is already running for this service"},"412":{"description":"No default S3 source configured"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}":{"get":{"tags":["Postgres Upgrades"],"summary":"Get a single upgrade by id, scoped to a service.","operationId":"get_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Upgrade","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/cancel":{"post":{"tags":["Postgres Upgrades"],"summary":"Cancel an in-flight upgrade. The orchestrator stops at its next phase\nboundary; already-terminal upgrades return 409.","operationId":"cancel_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cancellation requested","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Upgrade already terminal"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/logs":{"get":{"tags":["Postgres Upgrades"],"summary":"Get the accumulated JSONL log content for an upgrade (for dashboard display).","operationId":"get_pg_upgrade_logs","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Log content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeLogResponse"}}}},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/retry":{"post":{"tags":["Postgres Upgrades"],"summary":"Retry a failed upgrade. The phase is preserved, so the state machine\nresumes from where it failed.","operationId":"retry_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Retry scheduled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"400":{"description":"Upgrade is not in a retriable state"},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/rollback":{"post":{"tags":["Postgres Upgrades"],"summary":"Roll a completed upgrade back to its pre-upgrade PGDATA volume and old image.\nOnly valid while the rollback retention window is still open (see\n`ROLLBACK_RETENTION_DAYS`) and the rollback volume has not been swept.","operationId":"rollback_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Rollback complete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Upgrade is not in a rollbackable state (not completed, volume swept, or retention expired)"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/files/{file_path}":{"get":{"tags":["Files"],"operationId":"get_file","parameters":[{"name":"file_path","in":"path","description":"Relative path to the file from static directory","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File content retrieved successfully","content":{"application/octet-stream":{}}},"401":{"description":"Authentication required"},"403":{"description":"Access denied - path outside static directory or insufficient permissions"},"404":{"description":"File not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/geo/{ip}":{"get":{"tags":["geo"],"summary":"Get geolocation information for an IP address","operationId":"get_ip_geolocation","parameters":[{"name":"ip","in":"path","description":"IP address to geolocate (IPv4 or IPv6)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Geolocation information retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeoLocationResponse"}}}},"400":{"description":"Invalid IP address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP address not found in database","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/git-connections":{"get":{"tags":["Git Providers"],"summary":"List user's git provider connections","operationId":"list_connections","parameters":[{"name":"page","in":"query","description":"Page number for pagination (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (default: 30, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (created_at, updated_at, account_name)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc), default: desc","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of connections","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}":{"delete":{"tags":["Git Providers"],"summary":"Permanently delete a git provider connection","operationId":"delete_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Connection deleted successfully"},"400":{"description":"Connection is in use by projects and cannot be deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/activate":{"post":{"tags":["Git Providers"],"summary":"Activate a git provider connection","operationId":"activate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection activated successfully"},"400":{"description":"Provider is deactivated and connection cannot be activated"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/deactivate":{"post":{"tags":["Git Providers"],"summary":"Deactivate a git provider connection","operationId":"deactivate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection deactivated successfully"},"400":{"description":"Connection is in use by projects and cannot be deactivated"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/health-check":{"post":{"tags":["Git Provider Connections"],"summary":"Run an on-demand health check for a git connection.","description":"Probes the upstream (GitHub App, PAT, or OAuth token), persists the result,\nand fires admin notifications on status transitions. Returns the updated\nconnection.","operationId":"run_connection_health_check","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Health check completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/repositories":{"get":{"tags":["Git Providers"],"summary":"List repositories for a specific connection","description":"Fetches repositories from the connected git provider with support for pagination, search, and filtering.\nThis endpoint calls the provider's API directly to get the most up-to-date repository list.","operationId":"list_repositories_by_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, etc.)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/sync":{"post":{"tags":["Git Providers"],"summary":"Start a repository sync for a connection","description":"Kicks off a background sync of the connection's repositories from the\nprovider. Returns `202 Accepted` immediately — the caller should poll\nthe connection endpoint for `syncing` / `synced_repository_count`\nupdates rather than waiting on this response. The sync is guarded by\na hard deadline and always releases the `syncing` flag on exit, so a\nclient that disconnects mid-sync will not leave the connection stuck.","operationId":"sync_repositories","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Repository sync started in background","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositorySyncStartedResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"409":{"description":"Sync already in progress"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/update-token":{"post":{"tags":["Git Provider Connections"],"summary":"Update access token for a connection (when tokens expire or are rotated)","operationId":"update_connection_token","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTokenResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/validate":{"get":{"tags":["Git Provider Connections"],"summary":"Validate a connection by testing the access token","operationId":"validate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers":{"get":{"tags":["Git Providers"],"summary":"List all git providers","operationId":"list_git_providers","responses":{"200":{"description":"List of providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Git Providers"],"summary":"Create a new git provider configuration","operationId":"create_git_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderRequest"}}},"required":true},"responses":{"201":{"description":"Provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/bitbucket":{"post":{"tags":["Git Providers"],"summary":"Create a Bitbucket Cloud provider with access token or app password authentication","operationId":"create_bitbucket_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBitbucketRequest"}}},"required":true},"responses":{"201":{"description":"Bitbucket provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — missing or invalid auth fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/generic":{"post":{"tags":["Git Providers"],"summary":"Create a Generic git provider for self-hosted or arbitrary HTTPS git hosts.\nSupports public repositories (no token) and private repositories (token-based).","operationId":"create_generic_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGenericRequest"}}},"required":true},"responses":{"201":{"description":"Generic git provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — invalid clone URL or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitea/pat":{"post":{"tags":["Git Providers"],"summary":"Create a Gitea Personal Access Token provider","operationId":"create_gitea_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGiteaPATRequest"}}},"required":true},"responses":{"201":{"description":"Gitea PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — invalid URL or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/github/pat":{"post":{"tags":["Git Providers"],"summary":"Create a GitHub Personal Access Token provider","operationId":"create_github_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitHubPATRequest"}}},"required":true},"responses":{"201":{"description":"GitHub PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitlab/oauth":{"post":{"tags":["Git Providers"],"summary":"Create a GitLab OAuth provider","operationId":"create_gitlab_oauth_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitLabOAuthRequest"}}},"required":true},"responses":{"201":{"description":"GitLab OAuth provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitlab/pat":{"post":{"tags":["Git Providers"],"summary":"Create a GitLab PAT provider","operationId":"create_gitlab_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitLabPATRequest"}}},"required":true},"responses":{"201":{"description":"GitLab PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}":{"get":{"tags":["Git Providers"],"summary":"Get a specific git provider","operationId":"get_git_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Git Providers"],"summary":"Permanently delete a git provider","operationId":"delete_git_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider deleted successfully"},"400":{"description":"Provider has connections and cannot be deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/activate":{"post":{"tags":["Git Providers"],"summary":"Activate a git provider","operationId":"activate_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider activated successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/callback":{"get":{"tags":["Git Providers"],"summary":"Handle OAuth callback for a git provider","operationId":"handle_git_provider_oauth_callback","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"code","in":"query","description":"OAuth authorization code","required":true,"schema":{"type":"string"}},{"name":"state","in":"query","description":"CSRF state token","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to success page"},"400":{"description":"Bad request"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}}}},"/git-providers/{provider_id}/connections":{"get":{"tags":["Git Providers"],"summary":"Get connections for a specific git provider","operationId":"get_provider_connections","parameters":[{"name":"provider_id","in":"path","description":"Provider ID to get connections for","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of connections for the provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConnectionResponse"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/credentials":{"patch":{"tags":["Git Providers"],"summary":"Partially update credentials for an existing git provider. Only the fields\nyou send are replaced; omitted fields keep their stored values. Fields that\ndon't apply to the provider's auth method are ignored on the service side.","operationId":"update_git_provider_credentials","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderCredentialsRequest"}}},"required":true},"responses":{"200":{"description":"Credentials updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/deactivate":{"post":{"tags":["Git Providers"],"summary":"Deactivate a git provider","operationId":"deactivate_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider deactivated successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/deletion-check":{"get":{"tags":["Git Providers"],"summary":"Check if a git provider can be safely deleted","operationId":"check_provider_deletion_safety","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deletion check result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderDeletionCheckResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/oauth/authorize":{"get":{"tags":["Git Providers"],"summary":"Start OAuth flow for a git provider","operationId":"start_git_provider_oauth","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"302":{"description":"Redirect to OAuth provider"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/repositories":{"get":{"tags":["Git Providers"],"summary":"List all repositories for a specific provider","description":"Lists repositories synced to the database across every connection under\nthis provider, with the same pagination/filtering as `/repositories`.","operationId":"list_repositories_by_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, watchers, size, issues)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/safe-delete":{"delete":{"tags":["Git Providers"],"summary":"Safely delete a git provider (only if no projects are using it)","operationId":"delete_provider_safely","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider successfully deleted"},"400":{"description":"Cannot delete provider because it's in use"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git/public/{provider}/{owner}/{repo}":{"get":{"tags":["Public Repositories"],"summary":"Get information about a public repository (supports GitHub and GitLab)","operationId":"get_public_repository","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRepositoryInfo"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/git/public/{provider}/{owner}/{repo}/branches":{"get":{"tags":["Public Repositories"],"summary":"Get branches for a public repository (supports GitHub and GitLab)","operationId":"get_public_branches","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/git/public/{provider}/{owner}/{repo}/presets":{"get":{"tags":["Public Repositories"],"summary":"Detect presets for a public repository (supports GitHub and GitLab)","operationId":"detect_public_presets","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"branch","in":"query","description":"Branch name to detect presets for (default: repository's default branch)","required":false,"schema":{"type":["string","null"]}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Detected presets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPresetResponse"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository or branch not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/imports/discover":{"post":{"tags":["Imports"],"summary":"Discover workloads from a source","operationId":"discover_workloads","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverRequest"}}},"required":true},"responses":{"200":{"description":"List of discovered workloads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/execute":{"post":{"tags":["Imports"],"summary":"Execute an import","operationId":"execute_import","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteImportRequest"}}},"required":true},"responses":{"202":{"description":"Import execution started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteImportResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/plan":{"post":{"tags":["Imports"],"summary":"Create an import plan","operationId":"create_plan","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequest"}}},"required":true},"responses":{"200":{"description":"Import plan created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/sources":{"get":{"tags":["Imports"],"summary":"List available import sources","operationId":"list_sources","responses":{"200":{"description":"List of available import sources","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImportSourceInfo"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/{session_id}":{"get":{"tags":["Imports"],"summary":"Get import status","operationId":"get_import_status","parameters":[{"name":"session_id","in":"path","description":"Import session ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Import status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Import session not found"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}":{"get":{"tags":["Status Page"],"summary":"Get an incident by ID","operationId":"get_incident","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved incident","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}/status":{"patch":{"tags":["Status Page"],"summary":"Update incident status","operationId":"update_incident_status","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIncidentStatusRequest"}}},"required":true},"responses":{"200":{"description":"Incident status updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}/updates":{"get":{"tags":["Status Page"],"summary":"Get incident updates","operationId":"get_incident_updates","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved incident updates","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IncidentUpdateResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes":{"get":{"tags":["Nodes"],"summary":"List all registered nodes (admin — session auth via RequireAuth)","operationId":"admin_list_nodes","responses":{"200":{"description":"List of nodes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/register":{"post":{"tags":["Nodes"],"summary":"Register a new worker node or reconnect an existing one","operationId":"register_node","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeApiRequest"}}},"required":true},"responses":{"200":{"description":"Node reconnected successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeResponse"}}}},"201":{"description":"Node registered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeResponse"}}}},"400":{"description":"Validation error"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}":{"get":{"tags":["Nodes"],"summary":"Get a specific node by ID (admin — session auth via RequireAuth)","operationId":"admin_get_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeInfoResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Nodes"],"summary":"Remove a node from the cluster entirely. The node should be drained first\nto ensure containers have been rescheduled. If the node still has active\ncontainers, it will be drained automatically before removal.","operationId":"admin_remove_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveNodeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"409":{"description":"Node still has active containers"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/containers":{"get":{"tags":["Nodes"],"summary":"List all containers running on a specific node","operationId":"admin_list_node_containers","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Containers on this node","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeContainerListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/dns/ack":{"post":{"tags":["Internal DNS"],"summary":"`POST /internal/nodes/{node_id}/dns/ack`","operationId":"post_dns_ack","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsAckRequest"}}},"required":true},"responses":{"200":{"description":"ACK accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsAckResponse"}}}},"400":{"description":"ACK higher than server generation"},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/dns/changes":{"get":{"tags":["Internal DNS"],"summary":"`GET /internal/nodes/{node_id}/dns/changes?since=N`","operationId":"get_dns_changes","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"since","in":"query","description":"Highest generation the agent has already applied. Pass `0` to\nrequest a full zone snapshot. Defaults to `0` if omitted.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Diff or full snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsChangesResponse"}}}},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/drain":{"get":{"tags":["Nodes"],"summary":"Get the drain status for a node, including migration progress.","description":"Returns container counts and whether the drain is complete.\nCan be polled to track drain progress.","operationId":"admin_drain_status","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Drain status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrainStatusResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Nodes"],"summary":"Drain a node: mark it as \"draining\" so no new replicas are scheduled on it,\nand trigger redeployment of all affected environments so their containers\nare rescheduled to healthy nodes.","operationId":"admin_drain_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node drain initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrainNodeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Nodes"],"summary":"Undrain (reactivate) a node so it can accept new deployments again.\nOnly works for nodes in \"draining\" or \"drained\" status.","operationId":"admin_undrain_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node reactivated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UndrainNodeResponse"}}}},"400":{"description":"Node not in drainable state"},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/heartbeat":{"post":{"tags":["Nodes"],"summary":"Receive a heartbeat from a worker node","operationId":"node_heartbeat","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatApiRequest"}}},"required":true},"responses":{"200":{"description":"Heartbeat received","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/network/peers":{"get":{"tags":["Nodes"],"summary":"`GET /internal/nodes/{node_id}/network/peers`","operationId":"list_peers","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Peer list and self-allocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeerListResponse"}}}},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/s3-credentials/{s3_source_id}":{"get":{"tags":["Nodes"],"summary":"Get decrypted S3 credentials for a backup/restore operation.","description":"Agents call this endpoint to receive the S3 credentials they need to upload\nor download backups. The credentials are decrypted from the stored S3 source\nand returned over the authenticated TLS/WireGuard channel.","operationId":"get_s3_credentials","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"s3_source_id","in":"path","description":"S3 source ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3CredentialsResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"S3 source not found"},"500":{"description":"Internal server error"}}}},"/ip-access-control":{"get":{"tags":["IP Access Control"],"summary":"List all IP access control rules","operationId":"list_ip_access_control","parameters":[{"name":"action","in":"query","description":"Filter by action (\"block\" or \"allow\")","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of IP access control rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["IP Access Control"],"summary":"Create a new IP access control rule","operationId":"create_ip_access_control","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIpAccessControlRequest"}}},"required":true},"responses":{"201":{"description":"IP access control rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate IP address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ip-access-control/check/{ip}":{"get":{"tags":["IP Access Control"],"summary":"Check if an IP address is blocked","operationId":"check_ip_blocked","parameters":[{"name":"ip","in":"path","description":"IP address to check","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"IP block status"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ip-access-control/{id}":{"get":{"tags":["IP Access Control"],"summary":"Get a single IP access control rule by ID","operationId":"get_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"IP access control rule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["IP Access Control"],"summary":"Delete an IP access control rule","operationId":"delete_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"IP access control rule deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["IP Access Control"],"summary":"Update an IP access control rule","operationId":"update_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIpAccessControlRequest"}}},"required":true},"responses":{"200":{"description":"IP access control rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/kv/del":{"post":{"tags":["KV Store"],"summary":"Delete one or more keys","operationId":"kv_del","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DelRequest"}}},"required":true},"responses":{"200":{"description":"Keys deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DelResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/disable":{"delete":{"tags":["KV Management"],"summary":"Disable KV service","operationId":"kv_disable","responses":{"200":{"description":"KV service disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableKvResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"KV service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/enable":{"post":{"tags":["KV Management"],"summary":"Enable KV service","operationId":"kv_enable","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableKvRequest"}}},"required":true},"responses":{"200":{"description":"KV service enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableKvResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/expire":{"post":{"tags":["KV Store"],"summary":"Set expiration on a key","operationId":"kv_expire","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireRequest"}}},"required":true},"responses":{"200":{"description":"Expiration set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/get":{"post":{"tags":["KV Store"],"summary":"Get a value by key","operationId":"kv_get","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetRequest"}}},"required":true},"responses":{"200":{"description":"Value retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/incr":{"post":{"tags":["KV Store"],"summary":"Increment a numeric value","operationId":"kv_incr","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncrRequest"}}},"required":true},"responses":{"200":{"description":"Value incremented","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncrResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/keys":{"post":{"tags":["KV Store"],"summary":"Get keys matching a pattern","operationId":"kv_keys","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysRequest"}}},"required":true},"responses":{"200":{"description":"Keys retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/set":{"post":{"tags":["KV Store"],"summary":"Set a value with optional expiration","operationId":"kv_set","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetRequest"}}},"required":true},"responses":{"200":{"description":"Value set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/status":{"get":{"tags":["KV Management"],"summary":"Get KV service status","operationId":"kv_status","responses":{"200":{"description":"KV service status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KvStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/ttl":{"post":{"tags":["KV Store"],"summary":"Get time-to-live for a key","operationId":"kv_ttl","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TtlRequest"}}},"required":true},"responses":{"200":{"description":"TTL retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TtlResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/update":{"patch":{"tags":["KV Management"],"summary":"Update KV service configuration","operationId":"kv_update","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKvRequest"}}},"required":true},"responses":{"200":{"description":"KV service updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKvResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"KV service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/lb/routes":{"get":{"tags":["Load Balancer"],"operationId":"list_routes","responses":{"200":{"description":"List of routes","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RouteResponse"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["Load Balancer"],"operationId":"create_route","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRouteRequest"}}},"required":true},"responses":{"201":{"description":"Route created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"400":{"description":"Invalid request"}}}},"/lb/routes/{domain}":{"get":{"tags":["Load Balancer"],"operationId":"get_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Route found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"404":{"description":"Route not found"}}},"put":{"tags":["Load Balancer"],"operationId":"update_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRouteRequest"}}},"required":true},"responses":{"200":{"description":"Route updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"404":{"description":"Route not found"}}},"delete":{"tags":["Load Balancer"],"operationId":"delete_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Route deleted successfully"},"404":{"description":"Route not found"}}}},"/logout":{"post":{"tags":["Authentication"],"operationId":"logout","responses":{"200":{"description":"Successfully logged out"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/logs/context":{"get":{"tags":["Logs"],"summary":"Get context lines surrounding a specific log line","operationId":"get_log_context","parameters":[{"name":"chunk_id","in":"query","description":"Chunk ID","required":true,"schema":{"type":"string"}},{"name":"line_offset","in":"query","description":"Line offset within the chunk","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"lines","in":"query","description":"Context lines before and after (default: 25)","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"Context lines","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextLogsResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Chunk not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/logs/search":{"post":{"tags":["Logs"],"summary":"Search logs with structured filters and full text search","operationId":"search_logs","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchLogsRequest"}}},"required":true},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchLogsResponse"}}}},"400":{"description":"Invalid search parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/logs/tail":{"get":{"tags":["Logs"],"summary":"Live tail logs via Server-Sent Events","operationId":"tail_logs","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"string"}},{"name":"service","in":"query","description":"Service name","required":true,"schema":{"type":"string"}},{"name":"env","in":"query","description":"Environment","required":true,"schema":{"type":"string"}},{"name":"levels","in":"query","description":"Optional level filters","required":true,"schema":{"type":"array","items":{"type":"string"}}},{"name":"text","in":"query","description":"Optional text filter","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"SSE stream of log lines"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/monitors-health/projects":{"get":{"tags":["Status Page"],"summary":"Get monitor-based health summaries for multiple projects in a single query","operationId":"get_projects_monitor_health","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Health summaries per project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectsMonitorHealthResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}":{"get":{"tags":["Status Page"],"summary":"Get a monitor by ID","operationId":"get_monitor","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved monitor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Status Page"],"summary":"Delete a monitor","operationId":"delete_monitor","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Monitor deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/bucketed":{"get":{"tags":["Status Page"],"summary":"Get bucketed status data for a monitor using TimescaleDB","operationId":"get_bucketed_status","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"interval","in":"query","description":"Bucket interval: '5min', 'hourly', or 'daily' (default: hourly)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) (default: 24 hours ago)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) (default: now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved bucketed status data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusBucketedResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/current-status":{"get":{"tags":["Status Page"],"summary":"Get current status and uptime metrics for a monitor","operationId":"get_current_monitor_status","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Custom start time (ISO 8601) - overrides timeframe","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Custom end time (ISO 8601)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved current status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrentStatusResponse"}}}},"400":{"description":"Invalid time parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/uptime":{"get":{"tags":["Status Page"],"summary":"Get uptime history for a monitor","operationId":"get_uptime_history","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"days","in":"query","description":"Number of days of history (default: 60) - ignored if start_time/end_time provided","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) - overrides days parameter","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) - defaults to now","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved uptime history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UptimeHistoryResponse"}}}},"400":{"description":"Invalid time parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/nodes/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on a node.","operationId":"NodeMetricsGetRange","parameters":[{"name":"id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/notification-preferences":{"get":{"tags":["Notification Preferences"],"summary":"Get notification preferences","operationId":"get_preferences","responses":{"200":{"description":"Successfully retrieved preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Notification Preferences"],"summary":"Update notification preferences","operationId":"update_preferences","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePreferencesRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Notification Preferences"],"summary":"Delete notification preferences","operationId":"delete_preferences","responses":{"204":{"description":"Successfully deleted preferences"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers":{"get":{"tags":["Notification Providers"],"summary":"List all notification providers","operationId":"list_notification_providers","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Successfully retrieved providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}}},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Notification Providers"],"summary":"Create a new notification provider","operationId":"create_notification_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/cloudflare":{"post":{"tags":["Notification Providers"],"summary":"Create a new Cloudflare Email Sending notification provider","operationId":"create_cloudflare_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCloudflareProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Cloudflare provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/cloudflare/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Cloudflare Email Sending notification provider","operationId":"update_cloudflare_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCloudflareProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Cloudflare provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/email":{"post":{"tags":["Notification Providers"],"summary":"Create a new Email notification provider","operationId":"create_notification_email_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNotificationEmailProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Email provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/email/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update an Email notification provider","operationId":"update_notification_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateNotificationEmailProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Email provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/slack":{"post":{"tags":["Notification Providers"],"summary":"Create a new Slack notification provider","operationId":"create_slack_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSlackProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Slack provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/slack/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Slack notification provider","operationId":"update_slack_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlackProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Slack provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/webhook":{"post":{"tags":["Notification Providers"],"summary":"Create a new Webhook notification provider","description":"Webhook providers send notifications as JSON payloads to any HTTP endpoint.\nYou can configure custom headers for authentication (Bearer tokens, API keys, etc.).\nThe webhook will receive a JSON payload with notification details including:\nid, title, message, type, priority, severity, timestamp, and metadata.","operationId":"create_webhook_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Webhook provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/webhook/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Webhook notification provider","operationId":"update_webhook_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Webhook provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}":{"get":{"tags":["Notification Providers"],"summary":"Get a single notification provider","operationId":"get_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Notification Providers"],"summary":"Update a notification provider","operationId":"update_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid masked provider configuration"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Notification Providers"],"summary":"Delete a notification provider","operationId":"delete_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Successfully deleted provider"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}/config/{field}":{"get":{"tags":["Notification Providers"],"operationId":"reveal_notification_provider_config","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"field","in":"path","description":"Sensitive field, such as password or headers.Authorization","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sensitive provider configuration value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"Provider or field not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}/test":{"post":{"tags":["Notification Providers"],"summary":"Test a notification provider","operationId":"test_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/orders":{"get":{"tags":["Domains"],"summary":"List all ACME orders","operationId":"list_orders","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOrdersResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/otel/alerts":{"get":{"tags":["Alerts"],"summary":"List alert rules for a project (newest first, paginated).","operationId":"list_alerts","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Alert rules for the project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Alerts"],"summary":"Create a new alert rule for a project.","operationId":"create_alert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMetricAlertRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/alerts/preview":{"post":{"tags":["Alerts"],"summary":"Backtest an anomaly detector over a time range without saving a rule.","description":"Replays the metric against the same band the evaluator would use, returning\nthe per-bucket band + which points would have fired. Powers the form's\n\"would this have fired?\" preview and the explorer band overlay. Read-only.","operationId":"preview_alert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnomalyPreviewRequest"}}},"required":true},"responses":{"200":{"description":"Per-bucket band + breach points","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnomalyPreviewResponse"}}}},"400":{"description":"Not an anomaly detector / bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/alerts/{id}":{"get":{"tags":["Alerts"],"summary":"Fetch a single alert rule by id.","operationId":"get_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the lookup)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alert rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Alerts"],"summary":"Delete an alert rule.","operationId":"delete_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the delete)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Alerts"],"summary":"Update an alert rule's fields.","operationId":"update_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the update)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMetricAlertRequest"}}},"required":true},"responses":{"200":{"description":"Alert rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/dashboards":{"get":{"tags":["Dashboards"],"summary":"List dashboards for a project (newest first, paginated).","operationId":"list_dashboards","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Dashboards for the project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Dashboards"],"summary":"Create a new dashboard for a project.","operationId":"create_dashboard","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDashboardRequest"}}},"required":true},"responses":{"201":{"description":"Dashboard created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/dashboards/{id}":{"get":{"tags":["Dashboards"],"summary":"Fetch a single dashboard by id.","operationId":"get_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the lookup)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Dashboard","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Dashboards"],"summary":"Delete a dashboard.","operationId":"delete_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the delete)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Dashboard deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Dashboards"],"summary":"Update a dashboard's name and/or layout.","operationId":"update_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the update)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDashboardRequest"}}},"required":true},"responses":{"200":{"description":"Dashboard updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/genai/traces":{"get":{"tags":["GenAI"],"summary":"Query GenAI trace summaries — traces containing spans with `gen_ai.*` attributes.","description":"`duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`\nspan attributes (e.g. time-to-first-token, token latency) often follow the\nOTel GenAI semantic conventions, which use **seconds** (a fractional\ndouble), not milliseconds — do not read them as ms without converting.","operationId":"query_genai_traces","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"gen_ai_system","in":"query","description":"Filter by AI system (openai, anthropic, etc.)","required":false,"schema":{"type":"string"}},{"name":"gen_ai_model","in":"query","description":"Filter by model (gpt-4, claude-sonnet-4-20250514, etc.)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max traces to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"GenAI trace summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenAiTraceSummariesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/genai/traces/{project_id}/{trace_id}":{"get":{"tags":["GenAI"],"summary":"Get GenAI span details for a specific trace.","description":"`duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`\nspan attributes (e.g. time-to-first-token, token latency) often follow the\nOTel GenAI semantic conventions, which use **seconds** (a fractional\ndouble), not milliseconds — do not read them as ms without converting.","operationId":"get_genai_trace","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"path","description":"Trace ID (hex)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"GenAI trace span details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenAiTraceDetailResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/global/traces/{trace_id}":{"get":{"tags":["Traces"],"summary":"Assemble a unified cross-project span waterfall (Phase 2).","description":"Fans out to every project that holds spans for `trace_id` (up to 20\nprojects, 10,000 total spans). Spans are annotated with\n`project_id`/`project_name` and sorted by `start_time ASC`.\n`truncated: true` signals a hit on either cap; `truncated_projects`\nlists the dropped project IDs. See ADR-027 §4 for the full design.","operationId":"getUnifiedTrace","parameters":[{"name":"trace_id","in":"path","description":"Trace ID (32 lowercase hex characters)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Unified cross-project trace waterfall","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnifiedTrace"}}}},"400":{"description":"trace_id is not 32 lowercase hex characters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions or deployment token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/health/{project_id}":{"get":{"tags":["OTel"],"summary":"Get health summaries for a project.","operationId":"get_health","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Health summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/insights/{project_id}":{"get":{"tags":["Insights"],"summary":"List anomaly insights for a project.","operationId":"list_insights","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"status","in":"query","description":"Filter by status (active, resolved)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max insights to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Insights list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/logs":{"get":{"tags":["Telemetry Logs"],"summary":"Query log records with optional filters.","operationId":"query_logs","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"severity","in":"query","description":"Filter by severity (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Full-text search in log body (ILIKE)","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","description":"Filter by correlated trace ID","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max logs to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Log records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-label-keys":{"get":{"tags":["Telemetry Metrics"],"summary":"List the attribute (label) keys observed on a metric — powers the\nlabel-filter key autocomplete.","operationId":"list_metric_label_keys","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Metric to inspect","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Window start (RFC 3339); defaults to 24h before end","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Window end (RFC 3339); defaults to now","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Distinct label keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricLabelKeysResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-label-values":{"get":{"tags":["Telemetry Metrics"],"summary":"List the distinct values seen for a label key on a metric — powers value\nautocomplete once a key is chosen.","operationId":"list_metric_label_values","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Metric to inspect","required":true,"schema":{"type":"string"}},{"name":"label_key","in":"query","description":"Label key whose values to list (must match [a-zA-Z0-9_.:-])","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Window start (RFC 3339); defaults to 24h before end","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Window end (RFC 3339); defaults to now","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Distinct label values","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricLabelValuesResponse"}}}},"400":{"description":"Invalid label key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-names/{project_id}":{"get":{"tags":["Telemetry Metrics"],"summary":"List distinct metric names for a project.","operationId":"list_metric_names","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of metric names","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricNamesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metrics":{"get":{"tags":["Telemetry Metrics"],"summary":"Query metrics with time bucketing.","operationId":"query_metrics","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Filter by metric name","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"environment","in":"query","description":"Filter by deployment environment","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval (e.g. '1 hour', '5 minutes')","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max buckets to return (default: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"metric_type","in":"query","description":"Filter by metric type (gauge, sum, histogram, exponential_histogram, summary)","required":false,"schema":{"type":"string"}},{"name":"aggregation","in":"query","description":"Per-bucket aggregation: avg (default), sum, min, max, count, rate, p50/p95/p99, quantile:0.95","required":false,"schema":{"type":"string"}},{"name":"label_filters","in":"query","description":"Comma-separated key=value data-point label filters (keys must match [a-zA-Z0-9_.:-])","required":false,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Comma-separated label keys to group series by","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Metrics data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricsResponse"}}}},"400":{"description":"Invalid label key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/pipeline-stats":{"get":{"tags":["OTel"],"summary":"Get OTel pipeline statistics (admin/system view).","operationId":"get_pipeline_stats","responses":{"200":{"description":"Pipeline statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStatsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/quota/{project_id}":{"get":{"tags":["OTel"],"summary":"Get storage quota for a project.","operationId":"get_quota","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Storage quota","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotaResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/trace-summaries":{"get":{"tags":["Traces"],"summary":"Query trace summaries — one row per trace with span count, error count,\nroot span info, and proper trace-level pagination.","operationId":"query_trace_summaries","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"query","description":"Filter by trace ID","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by status (OK, ERROR)","required":false,"schema":{"type":"string"}},{"name":"min_duration_ms","in":"query","description":"Minimum trace duration in ms","required":false,"schema":{"type":"number","format":"double"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"name_pattern","in":"query","description":"Filter by span name pattern (ILIKE)","required":false,"schema":{"type":"string"}},{"name":"sort_by","in":"query","description":"Sort field: 'start_time' (default) or 'duration'","required":false,"schema":{"type":"string"}},{"name":"sort_order","in":"query","description":"Sort direction: 'asc' or 'desc' (default)","required":false,"schema":{"type":"string"}},{"name":"include_total","in":"query","description":"Compute the `total` count (default: true). Set false to skip the second aggregation when only the page is needed","required":false,"schema":{"type":"boolean"}},{"name":"limit","in":"query","description":"Max traces to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Trace summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TraceSummariesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces":{"get":{"tags":["Traces"],"summary":"Query trace spans with optional filters.","description":"Each returned span has a `duration_ms` field (float, milliseconds) — this is\nthe ONLY field guaranteed to be in milliseconds. Spans also carry an\n`attributes` map of raw key/value pairs exactly as reported by the\ninstrumenting library: numeric attribute values may be seconds, milliseconds,\nmicroseconds, or nanoseconds depending on that library's convention, and\nnothing in this response labels the unit. Never assume an attribute's\nnumeric value shares `duration_ms`'s unit, and never state a duration in\nmilliseconds unless it came from a `duration_ms` field.","operationId":"query_traces","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"query","description":"Filter by trace ID","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by status (OK, ERROR, UNSET)","required":false,"schema":{"type":"string"}},{"name":"min_duration_ms","in":"query","description":"Minimum span duration in ms","required":false,"schema":{"type":"number","format":"double"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Max spans to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Trace spans","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TracesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces/cross-project/{trace_id}":{"get":{"tags":["Traces"],"summary":"Discover sibling projects that share the same `trace_id` (Phase 1 banner).","description":"Returns an empty `siblings` list when the trace is single-project — never\n404. Project names are included so the UI can render navigation links\nwithout a second round-trip. See ADR-027 §3 for the full auth model and\ntopology-disclosure trade-offs.","operationId":"getCrossProjectTraceSiblings","parameters":[{"name":"trace_id","in":"path","description":"Trace ID (32 lowercase hex characters)","required":true,"schema":{"type":"string"}},{"name":"exclude_project_id","in":"query","description":"Project ID to exclude (the caller's own project) so the UI does not render a self-link","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Sibling projects sharing this trace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossProjectTraceResponse"}}}},"400":{"description":"trace_id is not 32 lowercase hex characters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions or deployment token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces/{project_id}/{trace_id}":{"get":{"tags":["Traces"],"summary":"Get all spans for a specific trace.","description":"Each span has a `duration_ms` field (float, milliseconds) — the ONLY field\nguaranteed to be in milliseconds — plus an `attributes` map of raw\nkey/value pairs exactly as the instrumenting library reported them.\nNumeric attribute values (e.g. connection-pool wait times, queue delays)\nmay be in seconds, milliseconds, microseconds, or nanoseconds depending on\nthat library's own convention; this response never labels the unit. When\nexplaining what a span spent time on, only quote milliseconds from\n`duration_ms` (or from `start_time`/`end_time` deltas) — never assume a raw\nattribute number is already in milliseconds.","operationId":"get_trace","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"path","description":"Trace ID (hex)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Trace spans tree","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TracesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/v1/logs":{"post":{"tags":["OTel Ingest"],"summary":"Ingest log records via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, routes high-severity logs\nto DB and all logs to S3.","operationId":"ingest_logs","requestBody":{"description":"OTLP ExportLogsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Logs accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/metrics":{"post":{"tags":["OTel Ingest"],"summary":"Ingest metrics via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, then stores.","operationId":"ingest_metrics","requestBody":{"description":"OTLP ExportMetricsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Metrics accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/traces":{"post":{"tags":["OTel Ingest"],"summary":"Ingest trace spans via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, then stores spans.","operationId":"ingest_traces","requestBody":{"description":"OTLP ExportTraceServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Traces accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/logs":{"post":{"tags":["OTel Ingest"],"summary":"Ingest log records with project/environment/deployment in the URL path.","operationId":"ingest_logs_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportLogsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Logs accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/metrics":{"post":{"tags":["OTel Ingest"],"summary":"Ingest metrics with project/environment/deployment in the URL path.","operationId":"ingest_metrics_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportMetricsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Metrics accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/traces":{"post":{"tags":["OTel Ingest"],"summary":"Ingest trace spans with project/environment/deployment in the URL path.","operationId":"ingest_traces_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportTraceServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Traces accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/performance/has-metrics":{"get":{"tags":["Performance"],"summary":"Check if performance metrics exist for a project","operationId":"has_performance_metrics","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully checked performance metrics availability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasMetricsResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/metrics":{"get":{"tags":["Performance"],"summary":"Get performance metrics","operationId":"get_performance_metrics","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved performance metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PerformanceMetricsResponse"}}}},"400":{"description":"Invalid date format or missing parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/metrics-over-time":{"get":{"tags":["Performance"],"summary":"Get metrics over time","operationId":"get_metrics_over_time","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved metrics over time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsOverTimeResponse"}}}},"400":{"description":"Invalid date format or missing parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/page-metrics":{"get":{"tags":["Performance"],"summary":"Get grouped page metrics","operationId":"get_grouped_page_metrics","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"group_by","in":"query","description":"Group by: path, country, region, city, device_type, browser, operating_system","required":true,"schema":{"type":"string"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved grouped page metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupedPageMetricsResponse"}}}},"400":{"description":"Invalid date format, missing parameters, or invalid group_by value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/platform/access-info":{"get":{"tags":["Platform"],"summary":"Get information about how the service is being accessed","description":"Returns details about the server's access mode, public IP address, private IP address,\nand domain creation capabilities. Both IP addresses are always included when available.","operationId":"get_access_info","responses":{"200":{"description":"Service access information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAccessInfo"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/platform/private-ip":{"get":{"tags":["Platform"],"summary":"Get private/local IP address of the server","operationId":"get_private_ip","responses":{"200":{"description":"Successfully retrieved private IP address"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/platform/public-ip":{"get":{"tags":["Platform"],"summary":"Get public IP address of the server","operationId":"get_public_ip","responses":{"200":{"description":"Successfully retrieved public IP address"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/presets":{"get":{"tags":["Presets"],"summary":"List all available presets","operationId":"list_presets","responses":{"200":{"description":"List of available presets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPresetsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/presets/{slug}/dockerfile":{"post":{"tags":["Presets"],"summary":"Generate a Dockerfile from a preset","description":"Returns the Dockerfile content and build arguments for a given preset slug.\nThe CLI can use this to build Docker images locally without needing a Dockerfile\nin the project directory, enabling zero-config deployments.","operationId":"generate_preset_dockerfile","parameters":[{"name":"slug","in":"path","description":"Preset slug (e.g., nextjs, vite, python)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateDockerfileRequest"}}},"required":true},"responses":{"200":{"description":"Generated Dockerfile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateDockerfileResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Preset not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/logs":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_logs","parameters":[{"name":"tail","in":"query","description":"Lines to tail (default 200, max 2000)","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/restart":{"post":{"tags":["Preview Gateway"],"operationId":"restart_preview_gateway","responses":{"204":{"description":"Gateway restarted"}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/settings":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_settings","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewGatewaySettingsResponse"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Preview Gateway"],"operationId":"patch_preview_gateway_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSettingsRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewGatewaySettingsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/status":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_status","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayStatus"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/upgrade":{"post":{"tags":["Preview Gateway"],"operationId":"upgrade_preview_gateway","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeRequest"}}},"required":true},"responses":{"204":{"description":"Gateway upgraded"}},"security":[{"bearer_auth":[]}]}},"/projects":{"get":{"tags":["Projects"],"summary":"Get a list of all projects","operationId":"get_projects","parameters":[{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Number of items per page","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedProjectList"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Projects"],"summary":"Create a new project","operationId":"create_project","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectRequest"}}},"required":true},"responses":{"200":{"description":"Project created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid input"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/by-slug/{slug}":{"get":{"tags":["Projects"],"summary":"Get details of a specific project by slug","operationId":"get_project_by_slug","parameters":[{"name":"slug","in":"path","description":"Project slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Project details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/from-template":{"post":{"tags":["Projects"],"summary":"Create a new project from a template","description":"Creates a new repository from a template and sets up the project with the\nspecified configuration. The template is cloned to a new repository under\nthe authenticated user's account or specified organization.","operationId":"create_project_from_template","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectFromTemplateRequest"}}},"required":true},"responses":{"201":{"description":"Project created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectFromTemplateResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Template not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/statistics":{"get":{"tags":["Projects"],"summary":"Get project statistics","operationId":"get_project_statistics","responses":{"200":{"description":"Project statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectStatisticsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}":{"get":{"tags":["Projects"],"summary":"Get details of a specific project","operationId":"get_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Project details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Projects"],"operationId":"update_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectRequest"}}},"required":true},"responses":{"200":{"description":"Project updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Projects"],"operationId":"delete_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Project deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}/deployments":{"get":{"tags":["Projects"],"operationId":"get_project_deployments","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"environment_id","in":"query","description":"Environment ID filter","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of deployments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentListResponse"}}}},"404":{"description":"Project not found"}}}},"/projects/{id}/last-deployment":{"get":{"tags":["Deployments"],"summary":"Get the last deployment for a specific project","operationId":"get_last_deployment","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Last deployment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project not found or no deployments"},"500":{"description":"Internal server error"}}}},"/projects/{id}/source":{"patch":{"tags":["Projects"],"summary":"Change a project's source type to a Git-less type (docker_image /\nstatic_files / manual). Switching TO Git is done via the Git settings\nendpoint (`POST /projects/{id}/git`), which also supplies the repository and\nprovider connection.","operationId":"change_project_source","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeProjectSourceRequest"}}},"required":true},"responses":{"200":{"description":"Source type changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid source type change (e.g. switching to Git here)"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}/trigger-pipeline":{"post":{"tags":["Projects"],"summary":"Trigger pipeline for a specific project","operationId":"trigger_project_pipeline","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerPipelinePayload"}}},"required":true},"responses":{"200":{"description":"Pipeline triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerPipelineResponse"}}}},"400":{"description":"Invalid request"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/active-visitors":{"get":{"tags":["Events"],"summary":"Get active visitors count","operationId":"get_active_visitors","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved active visitors count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveVisitorsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents":{"get":{"tags":["Agents"],"operationId":"list_agents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of agents for project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAgentsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAgentRequest"}}},"required":true},"responses":{"201":{"description":"Agent created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/cli-status":{"get":{"tags":["Agents"],"operationId":"get_cli_status","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"provider","in":"query","description":"AI provider: claude_cli or codex_cli","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"CLI status"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs":{"get":{"tags":["Agents"],"operationId":"list_all_runs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of all agent runs for a project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRunsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/latest-for-source":{"get":{"tags":["Agents"],"operationId":"latest_run_for_source","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trigger_source_type","in":"query","description":"Trigger source type, e.g. 'error_group'","required":true,"schema":{"type":"string"}},{"name":"trigger_source_id","in":"query","description":"Trigger source ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest matching run, or null if none","content":{"application/json":{"schema":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AgentRunResponse"}]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}":{"get":{"tags":["Agents"],"operationId":"get_run_with_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run with logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunWithLogsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/cancel":{"post":{"tags":["Agents"],"operationId":"cancel_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Agent run ID to cancel","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Run is already in a terminal state"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/retry":{"post":{"tags":["Agents"],"summary":"Retry a completed, failed, cancelled, or no_fix run with the same trigger context.\nCreates a new run record and spawns the executor.","operationId":"retry_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID to retry","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"New run created from retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Run is still active"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/stream":{"get":{"tags":["Agents"],"summary":"SSE endpoint for real-time streaming of run events.\nPolls the agent_run_logs table every 500ms for new entries and streams them.\nCloses when the run reaches a terminal status.","operationId":"stream_run_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Agent run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Server-Sent Events stream of run log events and terminal status","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/sandbox-status":{"get":{"tags":["Agents"],"operationId":"get_sandbox_status","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Project-scoped sandbox readiness (Docker + agent image)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/smoke-test":{"post":{"tags":["Agents"],"summary":"Run a smoke test to verify the selected AI CLI works in the environment\nwhere agents will actually execute (host or sandbox container). If no\n`provider_id` is supplied the globally active provider is tested.","operationId":"smoke_test_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"provider_id","in":"query","description":"Provider id to test; defaults to the globally active provider","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Smoke test result for the AI CLI in the agent's execution environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmokeTestResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}":{"get":{"tags":["Agents"],"operationId":"get_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Agent config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAgentRequest"}}},"required":true},"responses":{"200":{"description":"Agent updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Agent deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}/runs":{"get":{"tags":["Agents"],"operationId":"list_agent_runs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of runs for a specific agent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRunsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}/trigger":{"post":{"tags":["Agents"],"operationId":"trigger_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerAgentRequest"}}},"required":true},"responses":{"202":{"description":"Agent run created and queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"402":{"description":"Daily budget exceeded"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"422":{"description":"AI CLI not installed"},"429":{"description":"Cooldown active"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/aggregated-buckets":{"get":{"tags":["Events"],"summary":"Get aggregated metrics by time bucket","operationId":"get_aggregated_buckets","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for the query range","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for the query range","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Optional deployment filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Time bucket size: '1 hour', '1 day', '1 week', etc. (default: '1 hour')","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved aggregated buckets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AggregatedBucketsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations":{"get":{"tags":["AI Chat"],"summary":"Find the existing chat for a context (returns `null` if none yet). Requires\nthe per-project `ai_debug_chat_enabled` toggle to be on; returns 403 when the\nfeature is disabled so revoking it consistently hides existing chat content.","operationId":"find_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"context_type","in":"query","required":true,"schema":{"type":"string"}},{"name":"context_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ConversationResponse"}]}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]},"post":{"tags":["AI Chat"],"summary":"Get-or-create the chat for a context (seeds it on first open).","operationId":"create_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversationRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/list":{"get":{"tags":["AI Chat"],"summary":"List all active conversations for a project, most-recently-active first.\nPowers the conversation switcher in the AI assistant sidebar.","operationId":"list_conversations","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationResponse"}}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}":{"get":{"tags":["AI Chat"],"summary":"Full conversation history (excluding the internal system seed).","operationId":"get_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDetailResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AI Chat"],"summary":"Rename a conversation (set its human-facing title).","operationId":"rename_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameConversationRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationResponse"}}}},"400":{"description":""},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/archive":{"post":{"tags":["AI Chat"],"summary":"Archive (soft-delete) a conversation.","operationId":"archive_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/messages":{"post":{"tags":["AI Chat"],"summary":"Send a user message; stream the assistant reply as Server-Sent Events.","operationId":"send_message","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageRequest"}}},"required":true},"responses":{"200":{"description":"SSE stream of assistant text deltas","content":{"text/event-stream":{}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/pending-actions":{"get":{"tags":["AI Chat"],"summary":"List all pending actions for a conversation (most-recently-proposed first).","operationId":"list_pending_actions","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","description":"Conversation public id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PendingActionResponse"}}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}":{"get":{"tags":["AI Chat"],"summary":"Get a single pending action by its public id (scoped to the project).","operationId":"get_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}/confirm":{"post":{"tags":["AI Chat"],"summary":"Confirm a proposed AI action: validate permission, atomically claim, execute,\npersist outcome. The execution uses the CONFIRMING user's auth — never the model's.","operationId":"confirm_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"409":{"description":""},"503":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}/reject":{"post":{"tags":["AI Chat"],"summary":"Reject a proposed AI action (no execution). Status transitions to \"rejected\".","operationId":"reject_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"409":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms":{"get":{"tags":["Alarms"],"summary":"List alarms for a project with optional filters.","operationId":"listProjectAlarms","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_type","in":"query","description":"Filter by alarm type (e.g. `container_restart`, `outage`).","required":false,"schema":{"type":["string","null"]}},{"name":"status","in":"query","description":"Filter by status: `firing`, `acknowledged`, or `resolved`.","required":false,"schema":{"type":["string","null"]}},{"name":"severity","in":"query","description":"Filter by severity: `info`, `warning`, or `critical`.","required":false,"schema":{"type":["string","null"]}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"service_id","in":"query","description":"Filter by external service ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based, default 1).","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default 20, max 100).","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated list of alarms","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/summary":{"get":{"tags":["Alarms"],"summary":"Get alarm counts by status/severity/type for a project (dashboard summary widget).","operationId":"getProjectAlarmsSummary","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm summary counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmSummaryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/{alarm_id}/acknowledge":{"post":{"tags":["Alarms"],"summary":"Acknowledge a firing alarm (marks it as seen but not resolved).","operationId":"acknowledgeAlarm","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_id","in":"path","description":"Alarm ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm acknowledged"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alarm not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/{alarm_id}/resolve":{"post":{"tags":["Alarms"],"summary":"Resolve an alarm.","operationId":"resolveAlarm","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_id","in":"path","description":"Alarm ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm resolved"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alarm not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/analyze":{"post":{"tags":["Autofixer"],"summary":"Start an autofixer analysis run for the given error group.\nCreates the run record immediately and spawns analysis in the background.","operationId":"start_analysis","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAnalysisRequest"}}},"required":true},"responses":{"202":{"description":"Analysis started; returns run_id for streaming","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutofixerRunResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}":{"get":{"tags":["Autofixer"],"summary":"Get a single autofixer run with its logs.","operationId":"get_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run with logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutofixerRunWithLogsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/add-context":{"post":{"tags":["Autofixer"],"summary":"Append a user message to the run's context field.","operationId":"add_context","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddContextRequest"}}},"required":true},"responses":{"200":{"description":"Context appended"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/cancel":{"post":{"tags":["Autofixer"],"summary":"Cancel an autofixer run and clean up the work directory.","operationId":"cancel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run cancelled"},"400":{"description":"Run is already in a terminal state"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/create-pr":{"post":{"tags":["Autofixer"],"summary":"Push the fix branch and create a pull request.\nRequires phase == \"fix_ready\".","operationId":"create_pr","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"201":{"description":"PR created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePrResponse"}}}},"400":{"description":"Run not in fix_ready phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/fix":{"post":{"tags":["Autofixer"],"summary":"Transition from analysis to fix phase.\nRequires phase == \"analyzed\".","operationId":"start_fix","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Fix generation started"},"400":{"description":"Run not in analyzed phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/re-analyze":{"post":{"tags":["Autofixer"],"summary":"Continue the conversation with user feedback.\nUses the same Claude session (--continue) in the existing work directory.\nRequires phase == \"analyzed\".","operationId":"re_analyze","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Conversation continued with feedback"},"400":{"description":"Run not in analyzed phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/stream":{"get":{"tags":["Agents"],"summary":"SSE endpoint: streams run log events in real-time.\nPolls every 500 ms. Keeps the connection open through \"analyzed\" and \"fix_ready\"\nwaiting states; closes only on terminal statuses.","operationId":"stream_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Autofixer run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Server-Sent Events stream of autofixer run logs and status updates","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/automatic-deploy":{"post":{"tags":["Projects"],"summary":"Update automatic deployment setting for a project","operationId":"update_automatic_deploy","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAutomaticDeployRequest"}}},"required":true},"responses":{"200":{"description":"Automatic deployment setting updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains":{"get":{"tags":["Custom Domains"],"summary":"List all custom domains for a project","operationId":"list_custom_domains_for_project","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domains retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCustomDomainsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Custom Domains"],"summary":"Create a custom domain for a project","operationId":"create_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainRequest"}}},"required":true},"responses":{"201":{"description":"Custom domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"409":{"description":"Domain already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains/{domain_id}":{"get":{"tags":["Custom Domains"],"summary":"Get a custom domain by ID","operationId":"get_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domain retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Custom Domains"],"summary":"Update a custom domain","operationId":"update_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomDomainRequest"}}},"required":true},"responses":{"200":{"description":"Custom domain updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Custom Domains"],"summary":"Delete a custom domain","operationId":"delete_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Custom domain deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains/{domain_id}/link-certificate/{certificate_id}":{"post":{"tags":["Custom Domains"],"summary":"Link a custom domain to a certificate","operationId":"link_custom_domain_to_certificate","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"certificate_id","in":"path","description":"Certificate ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domain linked to certificate successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain or certificate not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-config":{"patch":{"tags":["Projects"],"summary":"Update deployment configuration for a project","operationId":"update_project_deployment_config","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeploymentConfigRequest"}}},"required":true},"responses":{"200":{"description":"Deployment configuration updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid deployment configuration"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens":{"get":{"tags":["Deployment Tokens"],"summary":"List all deployment tokens for a project","operationId":"list_deployment_tokens","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of deployment tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Deployment Tokens"],"summary":"Create a new deployment token for a project","operationId":"create_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenRequest"}}},"required":true},"responses":{"201":{"description":"Deployment token created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Token with this name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens/{token_id}":{"get":{"tags":["Deployment Tokens"],"summary":"Get a specific deployment token","operationId":"get_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment token details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Deployment Tokens"],"summary":"Delete a deployment token","operationId":"delete_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Deployment token deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Deployment Tokens"],"summary":"Update a deployment token","operationId":"update_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeploymentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Deployment token updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"409":{"description":"Token with this name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens/{token_id}/rotate":{"post":{"tags":["Deployment Tokens"],"summary":"Rotate a deployment token, invalidating its old secret and issuing a new one","operationId":"rotate_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment token rotated successfully; the response contains the new plaintext token, shown only once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}":{"get":{"tags":["Deployments"],"summary":"Get a specific deployment by ID for a project (identified by ID or slug)","operationId":"get_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/cancel":{"post":{"tags":["Projects"],"summary":"Cancel a deployment","operationId":"cancel_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment cancelled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"400":{"description":"Deployment cannot be cancelled (already completed, failed, or cancelled)"},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/container-logs":{"get":{"tags":["Deployments"],"summary":"List the captured (historical) container-log dumps for a deployment.","description":"Container runtime logs are normally only available live from the running\ncontainer. When a deployment is superseded its containers are torn down and\nthose logs would be lost — so just before teardown we capture each\ncontainer's logs to durable storage. This endpoint lists what was captured\nfor a given (often older) deployment, so a user can read the logs of a\ncontainer that no longer exists.","operationId":"list_deployment_container_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Captured container logs for the deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentContainerLogsListResponse"}}}},"404":{"description":"Deployment not found in this project"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/container-logs/{log_id}":{"get":{"tags":["Deployments"],"summary":"Get the captured text content of a single historical container-log dump.","operationId":"get_deployment_container_log_content","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"log_id","in":"path","description":"Captured log ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Captured container log content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentContainerLogContentResponse"}}}},"404":{"description":"Captured log not found in this project"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/jobs":{"get":{"tags":["Deployments"],"summary":"Get jobs for a specific deployment","description":"Returns all jobs (workflow tasks) for a deployment, ordered by execution order.\nThis replaces the old deployment stages endpoint.","operationId":"get_deployment_jobs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Jobs retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentJobsResponse"}}}},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/jobs/{job_id}/logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a specific deployment job","operationId":"get_deployment_job_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"job_id","in":"path","description":"Job ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job logs retrieved successfully","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Job or logs not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/jobs/{job_id}/logs/tail":{"get":{"tags":["Deployments"],"summary":"Tail logs for a specific deployment job in real-time via WebSocket","description":"**WebSocket Streaming**: Logs are sent as raw text, one line per WebSocket message.\n\n**Authentication**: Requires authentication via session cookie (browser clients)\nor API key (API clients). For browser-based WebSocket connections, ensure the user\nis logged in - the browser automatically includes session cookies in the WebSocket\nupgrade request.\n\n**API Client Authentication**: Include API key in Authorization header:\n```text\nAuthorization: Bearer tk_your_api_key_here\n```","operationId":"tail_deployment_job_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"job_id","in":"path","description":"Job ID","required":true,"schema":{"type":"string"}}],"responses":{"101":{"description":"WebSocket connection established for streaming deployment job logs"},"404":{"description":"Job or logs not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/operations":{"get":{"tags":["Deployments"],"summary":"Get all operations for a deployment","operationId":"get_deployment_operations","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of operations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Deployments"],"summary":"Execute a deployment operation (deploy, mark_complete, take_screenshot)","operationId":"execute_deployment_operation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteOperationRequest"}}},"required":true},"responses":{"202":{"description":"Operation executed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"400":{"description":"Invalid operation"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/operations/{operation_type}":{"get":{"tags":["Deployments"],"summary":"Get the status of a specific operation type","operationId":"get_deployment_operation_status","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"operation_type","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Operation status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Operation not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/pause":{"post":{"tags":["Projects"],"summary":"Pause a deployment","operationId":"pause_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment paused successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/promote":{"post":{"tags":["Deployments"],"summary":"Promote a deployment to another environment","description":"Creates a new deployment in the target environment using the source deployment's\nDocker image. Useful for promoting a validated preview/staging deployment to production.","operationId":"promote_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Source deployment ID to promote","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteDeploymentRequest"}}},"required":true},"responses":{"200":{"description":"Promotion initiated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"400":{"description":"Invalid deployment state for promotion"},"404":{"description":"Project, deployment, or target environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/resume":{"post":{"tags":["Projects"],"summary":"Resume a deployment","operationId":"resume_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment resumed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/rollback":{"post":{"tags":["Projects"],"operationId":"rollback_to_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID to rollback to","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Rollback initiated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/teardown":{"delete":{"tags":["Projects"],"summary":"Teardown a specific deployment","operationId":"teardown_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Deployment torn down successfully"},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/dsns":{"get":{"tags":[],"summary":"List all DSNs for a project","operationId":"list_dsns","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of DSNs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":[],"summary":"Create a new DSN for a project","operationId":"create_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDSNRequest"}}},"required":true},"responses":{"201":{"description":"DSN created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/get-or-create":{"post":{"tags":[],"summary":"Get or create DSN for a project/environment/deployment combination","operationId":"get_or_create_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrCreateDSNRequest"}}},"required":true},"responses":{"200":{"description":"DSN retrieved or created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/{dsn_id}/regenerate":{"post":{"tags":[],"summary":"Regenerate DSN keys (rotate keys)","operationId":"regenerate_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"dsn_id","in":"path","description":"DSN ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegenerateDSNRequest"}}},"required":true},"responses":{"200":{"description":"DSN keys regenerated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"DSN not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/{dsn_id}/revoke":{"post":{"tags":[],"summary":"Revoke (deactivate) a DSN","operationId":"revoke_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"dsn_id","in":"path","description":"DSN ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"DSN revoked"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"DSN not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/env-vars":{"get":{"tags":["Projects"],"summary":"Get environment variables for a project, optionally filtered by environment","operationId":"get_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment ID to filter by","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Create a new environment variable","operationId":"create_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnvironmentVariableRequest"}}},"required":true},"responses":{"201":{"description":"Environment variables created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/resolved":{"get":{"tags":["Projects"],"summary":"Resolved env vars for a project (manual + integration-sourced, merged).","description":"Returns the effective set of environment variables a deployment would see,\ncombining manually-defined vars with those contributed by linked external\nservices (Postgres, Redis, S3, etc.). Each entry is tagged with its source\nso the UI can render an integration icon, and manual entries that shadow an\nintegration key carry a reference to the integration they override.\n\nValues are always returned as a masked preview. Use the per-key reveal\nendpoint for plaintext (audit-logged).","operationId":"get_resolved_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment ID to filter manual vars by","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Resolved environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ResolvedEnvVarResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/resolved/{key}/value":{"get":{"tags":["Projects"],"summary":"Reveal the plaintext value of a resolved environment variable.","description":"Mirrors `GET /projects/{id}/env-vars/{key}/value` but handles keys sourced\nfrom linked integrations (which are not stored in the `env_vars` table).\nResolution order mirrors the merged view:\n\n1. Manual env var with this key — this endpoint reads the manual store when\n the key exists there, then writes its own reveal audit event so callers\n can safely use one endpoint regardless of source.\n2. Integration env var supplied by a linked external service.\n\nReturns 404 when neither a manual var nor an integration produces the key.","operationId":"get_resolved_environment_variable_value","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Environment variable key","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"query","description":"Exact manual environment-variable row ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"service_id","in":"query","description":"Integration service ID shown by the resolved list","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Resolved environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Project, key, or integration not found"},"409":{"description":"Environment variable key is ambiguous"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/{key}/value":{"get":{"tags":["Projects"],"summary":"Get environment variable value by key","operationId":"get_environment_variable_value","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Environment variable key","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"query","description":"Exact environment-variable row ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Project or variable not found"},"409":{"description":"Environment variable key is ambiguous"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/{var_id}":{"put":{"tags":["Projects"],"summary":"Update an environment variable","operationId":"update_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"path","description":"Environment variable ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentVariableRequest"}}},"required":true},"responses":{"200":{"description":"Environment variables updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project or variable not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Projects"],"summary":"Delete an environment variable","operationId":"delete_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"path","description":"Environment variable ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment variable deleted successfully"},"404":{"description":"Project or variable not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments":{"get":{"tags":["Projects"],"summary":"Get all environments for a project","operationId":"get_environments","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Create a new environment for a project","operationId":"create_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnvironmentRequest"}}},"required":true},"responses":{"201":{"description":"Environment created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}":{"get":{"tags":["Projects"],"summary":"Get a specific environment by ID or slug","operationId":"get_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Projects"],"summary":"Delete an environment permanently","description":"Permanently deletes an environment and all related data. Cannot delete:\n- Production environments (name = \"Production\")\n\nWarning: This action is permanent and cannot be undone.\nActive deployments are automatically cancelled before deletion.","operationId":"delete_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment permanently deleted"},"400":{"description":"Cannot delete production environment"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons":{"get":{"tags":["Crons"],"operationId":"get_environment_crons","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of cron jobs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CronInfo"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons/{cron_id}":{"get":{"tags":["Crons"],"operationId":"get_cron_by_id","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"cron_id","in":"path","description":"Cron Job ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cron job details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CronInfo"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Cron job not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons/{cron_id}/executions":{"get":{"tags":["Crons"],"operationId":"get_cron_executions","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"cron_id","in":"path","description":"Cron Job ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"List of cron job executions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CronExecutionInfo"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Cron job not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/domains":{"get":{"tags":["Projects"],"summary":"Get all environment domains for a specific environment","operationId":"get_environment_domains","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentDomainResponse"}}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Add a new environment domain","operationId":"add_environment_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEnvironmentDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentDomainResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/domains/{domain_id}":{"delete":{"tags":["Projects"],"summary":"Delete an environment domain","operationId":"delete_environment_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Domain deleted successfully"},"404":{"description":"Project, environment, or domain not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/settings":{"put":{"tags":["Projects"],"summary":"Update environment settings","operationId":"update_environment_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Environment settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/sleep":{"post":{"tags":["Environments"],"summary":"Sleep an on-demand environment","description":"Manually put an on-demand environment to sleep. Stops containers and sets\n`sleeping = true`. If no OnDemandWaker is available, falls back to DB flag only.","operationId":"sleep_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment put to sleep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"On-demand not enabled for this environment"},"404":{"description":"Environment not found"},"429":{"description":"Too many state transitions, retry after cooldown"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/subdomain":{"patch":{"tags":["Projects"],"summary":"Rename the auto-managed subdomain for an environment.","description":"Replaces the environment's previous subdomain entirely — the old\nhostname stops resolving once the proxy reloads its route table.\nCustom domains attached to the environment are unaffected.","operationId":"update_environment_subdomain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentSubdomainRequest"}}},"required":true},"responses":{"200":{"description":"Subdomain updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"Invalid subdomain or conflict with another environment"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/teardown":{"delete":{"tags":["Projects"],"summary":"Teardown an environment and all its active deployments","operationId":"teardown_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment torn down successfully"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/wake":{"post":{"tags":["Environments"],"summary":"Wake a sleeping on-demand environment","description":"Manually wake an environment that has been put to sleep by the on-demand\nidle timeout. Starts containers, waits for health checks, then sets\n`sleeping = false`. If no OnDemandWaker is available (proxy not running\nin same process), falls back to setting the DB flag only.","operationId":"wake_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment woken up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"On-demand not enabled for this environment"},"404":{"description":"Environment not found"},"429":{"description":"Too many state transitions, retry after cooldown"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/container-logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a container in an environment via WebSocket","operationId":"get_container_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"end_date","in":"query","description":"End date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tail","in":"query","description":"Number of lines to tail (or 'all')","required":false,"schema":{"type":"string"}},{"name":"container_name","in":"query","description":"Optional container name (defaults to first/primary container)","required":false,"schema":{"type":"string"}},{"name":"timestamps","in":"query","description":"Include timestamps in log output (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"follow","in":"query","description":"Follow log output in real-time (default: true)","required":false,"schema":{"type":"boolean"}}],"responses":{"101":{"description":"WebSocket connection established for streaming container logs"},"400":{"description":"Not a server-type project"},"404":{"description":"Project, deployment, or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers":{"get":{"tags":["Deployments"],"summary":"List all containers for an environment","operationId":"list_containers","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of containers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerListResponse"}}}},"400":{"description":"Not a server-type project"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}":{"get":{"tags":["Containers"],"summary":"Get detailed information about a specific container","operationId":"get_container_detail","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerDetailResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/environment/{variable_name}":{"get":{"tags":["Containers"],"operationId":"get_container_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"variable_name","in":"path","description":"Environment variable name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerEnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Container or environment variable not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a specific container by container ID via WebSocket","operationId":"get_container_logs_by_id","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"end_date","in":"query","description":"End date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tail","in":"query","description":"Number of lines to tail (or 'all')","required":false,"schema":{"type":"string"}},{"name":"timestamps","in":"query","description":"Include timestamps in log output (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"follow","in":"query","description":"Follow log output in real-time (default: true)","required":false,"schema":{"type":"boolean"}}],"responses":{"101":{"description":"WebSocket connection established for streaming container logs"},"400":{"description":"Not a server-type project"},"404":{"description":"Project, environment, or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics":{"get":{"tags":["Containers"],"summary":"Get metrics/stats for a specific container","operationId":"get_container_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container metrics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerMetricsResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics/history":{"get":{"tags":["Containers"],"summary":"Fetch a time-series range for a single container resource metric\n(recorded by the container health monitor every ~30s).","description":"Useful metric names: `container.cpu_percent`,\n`container.cpu_utilization_percent`, `container.memory_used_bytes`,\n`container.memory_percent`, `container.network_rx_bytes_delta`,\n`container.network_tx_bytes_delta`.","operationId":"ContainerMetricsGetHistory","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"metric","in":"query","description":"Dotted metric name, e.g. `container.cpu_percent` or\n`container.memory_used_bytes`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `1h`, `6h`, `24h`, or `7d` (defaults to `1h`).","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerMetricHistoryPoint"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Container not found"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics/stream":{"get":{"tags":["Containers"],"summary":"Stream container metrics via Server-Sent Events (SSE)","operationId":"stream_container_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"interval","in":"query","description":"Update interval in milliseconds (default: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Metrics stream established (Server-Sent Events)"},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/restart":{"post":{"tags":["Containers"],"summary":"Restart a container","operationId":"restart_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container restarted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/start":{"post":{"tags":["Containers"],"summary":"Start a container","operationId":"start_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/stop":{"post":{"tags":["Containers"],"summary":"Stop a specific container","operationId":"stop_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container stopped successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/deploy/image":{"post":{"tags":["Deployments"],"summary":"Deploy from an external Docker image","description":"Triggers a deployment using a pre-built Docker image from an external registry.\nThe image will be pulled and deployed to the specified environment.","operationId":"deploy_from_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployFromImageRequest"}}},"required":true},"responses":{"202":{"description":"Deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/deploy/image-upload":{"post":{"tags":["Deployments"],"summary":"Deploy from an uploaded Docker image tarball","description":"Uploads a Docker image tarball (from `docker save`) and deploys it directly.\nThe image is imported using `docker load` and then deployed to the specified environment.\nThis is useful when you want to deploy an image without pushing to a registry first.\n\nThe uploaded file should be a tarball created by `docker save myimage:tag > image.tar`\nor `docker save myimage:tag | gzip > image.tar.gz` (gzip compressed tarballs are also supported).","operationId":"deploy_from_image_upload","parameters":[{"name":"tag","in":"query","description":"Tag to apply to the imported image (e.g., \"myapp:v1.0\")\nIf not provided, a unique tag will be generated","required":false,"schema":{"type":["string","null"]}},{"name":"health_check_path","in":"query","description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nMust start with '/'. When omitted, defaults to \"/\".","required":false,"schema":{"type":["string","null"]}},{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Image imported and deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request or unsupported format"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project or environment not found"},"413":{"description":"Image tarball too large"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/deploy/static":{"post":{"tags":["Deployments"],"summary":"Deploy from an uploaded static bundle","description":"Triggers a deployment using a previously uploaded static file bundle.","operationId":"deploy_from_static","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployFromStaticRequest"}}},"required":true},"responses":{"202":{"description":"Deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project, environment, or bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/error-alert-rules":{"get":{"tags":["error-alert-rules"],"summary":"List all alert rules for a project","operationId":"list_alert_rules","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of alert rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlertRuleResponse"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["error-alert-rules"],"summary":"Create a new alert rule","operationId":"create_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertRuleRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"400":{"description":"Validation error"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-alert-rules/{rule_id}":{"get":{"tags":["error-alert-rules"],"summary":"Get a specific alert rule","operationId":"get_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alert rule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["error-alert-rules"],"summary":"Update an existing alert rule","operationId":"update_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertRuleRequest"}}},"required":true},"responses":{"200":{"description":"Alert rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["error-alert-rules"],"summary":"Delete an alert rule","operationId":"delete_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-dashboard-stats":{"get":{"tags":["error-tracking"],"summary":"Get error dashboard statistics","operationId":"get_error_dashboard_stats","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"end_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"environment_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"compare_to_previous","in":"query","required":false,"schema":{"type":["boolean","null"]}}],"responses":{"200":{"description":"Error dashboard statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDashboardStatsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups":{"get":{"tags":["error-tracking"],"summary":"List error groups for a project","operationId":"list_error_groups","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"status","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"environment_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_date","in":"query","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"end_date","in":"query","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of error groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedErrorGroupsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}":{"get":{"tags":["error-tracking"],"summary":"Get a specific error group","operationId":"get_error_group","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error group details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorGroupResponse"}}}},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["error-tracking"],"summary":"Update error group status","operationId":"update_error_group","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateErrorGroupRequest"}}},"required":true},"responses":{"200":{"description":"Error group updated successfully"},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}/events":{"get":{"tags":["error-tracking"],"summary":"List error events for a specific group","operationId":"list_error_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated list of error events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedErrorEventsResponse"}}}},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}/events/{event_id}":{"get":{"tags":["error-tracking"],"summary":"Get a specific error event","operationId":"get_error_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"event_id","in":"path","description":"Error event ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Error event details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEventResponse"}}}},"404":{"description":"Event not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-stats":{"get":{"tags":["error-tracking"],"summary":"Get error statistics for a project","operationId":"get_error_stats","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorGroupStatsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-time-series":{"get":{"tags":["error-tracking"],"summary":"Get error time series data for charts","operationId":"get_error_time_series","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"end_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"bucket","in":"query","description":"Time bucket size (e.g., \"1h\", \"15m\", \"1d\", \"1 hour\", \"30 minutes\")","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Error time series data","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ErrorTimeSeriesDataResponse"}}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/events":{"get":{"tags":["Events"],"summary":"Get event counts with filtering","operationId":"get_events_count","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of events to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"custom_events_only","in":"query","description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event counts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventCount"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/breakdown":{"get":{"tags":["Events"],"summary":"Get event type breakdown","operationId":"get_event_type_breakdown","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event type breakdown","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTypeBreakdown"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/ingest":{"post":{"tags":["Events"],"summary":"Record an analytics event via the console API with explicit project ID.","description":"The app backend forwards the user's encrypted Temps cookies, so visitor/session\nidentity is resolved automatically by middleware. No geolocation or user-agent\nenrichment is performed — this is a lightweight server-side ingestion path.","operationId":"record_console_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsoleEventPayload"}}},"required":true},"responses":{"200":{"description":"Event recorded successfully"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/properties/breakdown":{"get":{"tags":["Events"],"summary":"Get property breakdown by grouping events by a column","operationId":"get_property_breakdown","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Column to group by (channel, device_type, browser, etc.)","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by event name","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors - default: events","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of results (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"filter_country","in":"query","description":"Filter by country (for region/city drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter by region (for city drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter by browser name (for version drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_os","in":"query","description":"Filter by OS name (for version drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"Filter by channel name (for channel drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"Filter by referrer hostname (for referrer drill-downs)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved property breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyBreakdownResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/properties/timeline":{"get":{"tags":["Events"],"summary":"Get property timeline by grouping events by a column over time","operationId":"get_property_timeline","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Column to group by (channel, device_type, browser, etc.)","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by event name","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors - default: events","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Time bucket: hour, day, week, month (default: auto-detect)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved property timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyTimelineResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/timeline":{"get":{"tags":["Events"],"summary":"Get events timeline","operationId":"get_events_timeline","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by specific event name","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Bucket size: hour, day, or week (auto-detected if not specified)","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved events timeline","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/unique":{"get":{"tags":["Funnels"],"summary":"Get all unique/distinct event types for a project (paginated)","operationId":"get_unique_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Unique event types retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventTypesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/external-images":{"get":{"tags":["External Images"],"summary":"List external images for a project","operationId":"list_remote_external_images","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of external images","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedExternalImagesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["External Images"],"summary":"Register an external Docker image","description":"Registers an external Docker image reference without triggering a deployment.\nThe image can be deployed later using the deploy/image endpoint.","operationId":"register_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterImageRequest"}}},"required":true},"responses":{"201":{"description":"Image registered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalImageResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/external-images/{image_id}":{"get":{"tags":["External Images"],"summary":"Get details of a specific external image","operationId":"get_remote_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Image details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalImageResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["External Images"],"summary":"Delete an external image","operationId":"delete_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Image deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels":{"get":{"tags":["Funnels"],"summary":"List all funnels for a project","operationId":"list_funnels","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Funnels retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FunnelResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Funnels"],"summary":"Create a new funnel","operationId":"create_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"201":{"description":"Funnel created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/preview":{"post":{"tags":["Funnels"],"summary":"Preview funnel metrics without creating the funnel","operationId":"preview_funnel_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"200":{"description":"Funnel metrics preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunnelMetricsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/{funnel_id}":{"put":{"tags":["Funnels"],"summary":"Update a funnel","operationId":"update_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"200":{"description":"Funnel updated successfully"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Funnels"],"summary":"Delete a funnel","operationId":"delete_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Funnel deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/{funnel_id}/metrics":{"get":{"tags":["Funnels"],"summary":"Get funnel metrics","operationId":"get_funnel_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"country_code","in":"query","description":"Country code filter","required":false,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date filter (ISO 8601)","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date filter (ISO 8601)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Funnel metrics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunnelMetricsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/git":{"post":{"tags":["Projects"],"summary":"Update git settings for a project","operationId":"update_git_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGitSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Git settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid git configuration or branch does not exist"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/gitlab/reinstall-webhook":{"post":{"tags":["Projects"],"summary":"Reinstall the GitLab webhook for a project","description":"Removes the existing webhook (if any) and installs a fresh one.\nUse this when a webhook has been manually deleted on the GitLab side\nand automatic deployments have stopped working.","operationId":"reinstall_gitlab_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Webhook reinstalled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReinstallWebhookResponse"}}}},"400":{"description":"Project is not connected to a GitLab repository"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/has-error-groups":{"get":{"tags":["error-tracking"],"summary":"Check if project has any error groups","operationId":"has_error_groups","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error groups existence check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasErrorGroupsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/has-events":{"get":{"tags":["Events"],"summary":"Check if project has any analytics events","operationId":"has_analytics_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully checked for events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasEventsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/hourly-visits":{"get":{"tags":["Events"],"summary":"Get hourly visits","operationId":"get_hourly_visits","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering visits","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering visits","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events (page views), sessions (unique sessions), or visitors (unique visitors) - default: events","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved hourly visits","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images":{"get":{"tags":["External Images"],"summary":"List all external images for a project","operationId":"list_external_images","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of external images","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images/push":{"post":{"tags":["External Images"],"summary":"Push an external Docker image","operationId":"push_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushImageRequest"}}},"required":true},"responses":{"201":{"description":"Image pushed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images/{image_id}":{"get":{"tags":["External Images"],"summary":"Get details of a specific external image","operationId":"get_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Image details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/incidents":{"get":{"tags":["Status Page"],"summary":"List incidents for a project","operationId":"list_incidents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"status","in":"query","description":"Filter by status","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved incidents"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Status Page"],"summary":"Create a new incident","operationId":"create_incident","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIncidentRequest"}}},"required":true},"responses":{"201":{"description":"Incident created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/incidents/bucketed":{"get":{"tags":["Status Page"],"summary":"Get bucketed incident data for a project","operationId":"get_bucketed_incidents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"interval","in":"query","description":"Bucket interval: '5min', 'hourly', or 'daily' (default: hourly)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) (default: 7 days ago)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) (default: now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved bucketed incident data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentBucketedResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/logs":{"delete":{"tags":["Logs"],"summary":"Purge all logs for a project before a given timestamp","operationId":"purge_project_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurgeLogsRequest"}}},"required":true},"responses":{"200":{"description":"Purge completed"},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers":{"get":{"tags":["Agents"],"operationId":"list_mcps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMcpsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMcpRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers/{slug}":{"get":{"tags":["Agents"],"operationId":"get_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMcpRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"MCP server deleted"},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers/{slug}/config/{field}":{"get":{"tags":["Agents"],"operationId":"reveal_mcp_config","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}},{"name":"field","in":"path","description":"Sensitive field path, such as url or env.API_TOKEN","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveMcpConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"401":{"description":"Unauthorized"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"MCP server or field not found"},"500":{"description":"Configuration read or audit failed"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/monitors":{"get":{"tags":["Status Page"],"summary":"List monitors for a project","operationId":"list_monitors","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved monitors","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MonitorResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Status Page"],"summary":"Create a new monitor","operationId":"create_monitor","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMonitorRequest"}}},"required":true},"responses":{"201":{"description":"Monitor created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/observe/events":{"get":{"tags":["Observability"],"summary":"List a merged page of observability events for a project.","description":"Each row carries everything the side panel needs to render — no\nfollow-up fetch is required for the common case. Heavy fields\n(stacktraces, headers, span attributes) are truncated server-side and\nexpose a `*_truncated` flag; clients fetch the full row from the\n`/full` endpoint only when the user explicitly clicks \"Show full\".","operationId":"observability_list_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"kinds","in":"query","description":"Comma-separated kinds: `log,request,span,error,revenue`. Empty or\nmissing returns every kind.","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","description":"Inclusive lower bound on event timestamp (ISO 8601, `Z` suffix).","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Inclusive upper bound on event timestamp.","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"deployment_id","in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"search","in":"query","description":"Free-text substring matched against per-kind summary fields\n(request path / error class / revenue event_type).","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size (default 50, max 200).","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"hide_bots","in":"query","description":"When `true`, exclude bot/crawler request rows. When `false`, only\ninclude bot rows. Omitted means \"include everything\" (default).\nOnly affects the `Request` kind.","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Merged event page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsResponse"}}}},"400":{"description":"Invalid filter (kinds, time range, …)","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"text/plain":{"schema":{"type":"string"}}}},"403":{"description":"Insufficient permissions","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/observe/events/{kind}/{event_id}/full":{"get":{"tags":["Observability"],"summary":"Fetch the un-truncated form of one event by `(kind, id)`. Side panel\n\"Show full\" action calls this — the list response carries truncated\npreviews + a `*_truncated` flag to let the UI decide whether to fetch.","operationId":"observability_full_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"kind","in":"path","description":"Event kind discriminator","required":true,"schema":{"$ref":"#/components/schemas/EventKind"}},{"name":"event_id","in":"path","description":"Per-kind identity: request_id for requests, `{trace_id}:{span_id}` for spans, serial id for errors/revenue","required":true,"schema":{"type":"string"}},{"name":"ts","in":"query","description":"The row's event timestamp as returned by the list endpoint. Optional,\nbut strongly recommended: it bounds the lookup to the storage\npartitions/chunks around that instant instead of scanning the whole\nretention window.","required":false,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Full row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FullEvent"}}}},"401":{"description":"Unauthorized","content":{"text/plain":{"schema":{"type":"string"}}}},"403":{"description":"Insufficient permissions","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Event not found in project","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/releases/{release}/source-files":{"get":{"tags":["source-maps"],"summary":"List uploaded source files for a release (metadata only).","operationId":"list_source_files","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of source files","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceFileListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["source-maps"],"summary":"Upload a raw source file for a release (native symbolication).","description":"Accepts a multipart form with:\n- `file`: the source file bytes (required)\n- `file_path`: the path of the file as it appears in stack frames (required;\n derived from the uploaded filename if omitted). Normalized with the `~`\n prefix convention, matching source-map storage.\n\nRequires the project's `error_source_context_enabled` toggle to be on.\nUpserts on (project, release, file_path).","operationId":"upload_source_file","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Source file uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceFileResponse"}}}},"400":{"description":"Missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Source context disabled for project"},"413":{"description":"Source file too large"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["source-maps"],"summary":"Delete all uploaded source files for a release.","operationId":"delete_release_source_files","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Source files deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/releases/{release}/source-maps":{"get":{"tags":["source-maps"],"summary":"List all source maps for a specific release","operationId":"list_source_maps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of source maps","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceMapListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["source-maps"],"summary":"Upload a source map for a release.","description":"Accepts a multipart form with:\n- `file`: The .map file (required)\n- `file_path`: The URL path of the minified file as it appears in stack traces (required).\n Uses the ~ prefix convention (e.g., \"~/assets/main.js\").\n If a full URL is provided, it will be normalized automatically.\n- `dist`: Optional distribution identifier\n\nIf a source map already exists for the same (project, release, file_path), it is replaced.","operationId":"upload_source_map","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Source map uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceMapResponse"}}}},"400":{"description":"Invalid source map or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"413":{"description":"Source map too large"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["source-maps"],"summary":"Delete all source maps for a specific release","operationId":"delete_release_source_maps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Source maps deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/events":{"get":{"tags":["Revenue"],"summary":"Recent ingested events for the activity feed.","operationId":"revenue_recent_events","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecentEventResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations":{"get":{"tags":["Revenue"],"summary":"List revenue integrations for a project.","operationId":"revenue_list_integrations","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IntegrationResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Revenue"],"summary":"Create a new revenue integration. Response contains the generated\nwebhook path that the user must paste into their provider's dashboard.","operationId":"revenue_create_integration","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIntegrationBody"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"409":{"description":"Already connected"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}":{"delete":{"tags":["Revenue"],"summary":"Delete a revenue integration (permanent — use rotate_token to refresh\ncredentials without breaking history).","operationId":"revenue_delete_integration","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/config":{"post":{"tags":["Revenue"],"summary":"Replace the typed provider config on an integration. Passing `null`\nclears the config back to the accept-everything default. The config's\nprovider tag must match the integration's provider.","operationId":"revenue_update_config","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConfigBody"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Integration not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/import/invoices":{"post":{"tags":["Revenue"],"summary":"Import a Stripe invoices CSV export. Each paid invoice becomes an\n`invoice.paid` event so historical MRR/charge totals populate the\ntimeseries. Ingestion is idempotent: re-uploading the same file is a\nno-op.","operationId":"revenue_import_invoices_csv","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOutcomeResponse"}}}},"400":{"description":"Malformed CSV or wrong provider"},"404":{"description":"Integration not found"},"413":{"description":"CSV too large"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/import/subscriptions":{"post":{"tags":["Revenue"],"summary":"Import a Stripe subscriptions CSV export. Use this to backfill MRR /\nactive subscriptions when migrating from Stripe without providing\nAPI keys. Webhooks remain the source of truth for live updates —\nCSV rows never overwrite newer webhook state.","operationId":"revenue_import_subscriptions_csv","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOutcomeResponse"}}}},"400":{"description":"Malformed CSV or wrong provider"},"404":{"description":"Integration not found"},"413":{"description":"CSV too large"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/rotate-token":{"post":{"tags":["Revenue"],"summary":"Rotate the webhook path token. Returns the new integration state —\nthe user must paste the new URL into their provider's dashboard.","operationId":"revenue_rotate_token","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/update-secret":{"post":{"tags":["Revenue"],"summary":"Replace the stored signing secret without rotating the webhook URL.\nUse this after rotating the secret in the provider's dashboard.","operationId":"revenue_update_secret","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSecretBody"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Integration not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/customers":{"get":{"tags":["Revenue"],"summary":"New + churned customers per bucket.","operationId":"revenue_metrics_customers","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomerMovementResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/mrr":{"get":{"tags":["Revenue"],"summary":"Bucketed MRR timeseries for the revenue chart.","operationId":"revenue_metrics_mrr","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MrrBucketResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/summary":{"get":{"tags":["Revenue"],"summary":"Current MRR / ARR / churn / ARPU for a project, in one currency.","operationId":"revenue_metrics_summary","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsSummaryResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/secrets":{"get":{"tags":["Secrets"],"summary":"List project secrets (metadata only — values never returned).","operationId":"listProjectSecrets","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment filter","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of secrets (metadata only, no values)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Secrets"],"summary":"Create a new secret. The value is encrypted before storage and will be\nmounted as a file at `/run/secrets/` on the next deployment.\nThe plaintext value is NOT returned — the response carries only metadata.","operationId":"createProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectSecretRequest"}}},"required":true},"responses":{"201":{"description":"Secret created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}},"400":{"description":"Invalid key or value too large"},"409":{"description":"Key already exists in project"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/secrets/{secret_id}":{"put":{"tags":["Secrets"],"summary":"Update a project secret. Value rotation requires a redeploy to take effect —\nrunning containers keep their currently-mounted values until the next\ndeployment.","operationId":"updateProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"secret_id","in":"path","description":"Secret ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectSecretRequest"}}},"required":true},"responses":{"200":{"description":"Secret updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}},"400":{"description":"Value too large"},"404":{"description":"Secret not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Secrets"],"summary":"Delete a project secret. Running containers keep their mounted secret files\nuntil they are redeployed.","operationId":"deleteProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"secret_id","in":"path","description":"Secret ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Secret deleted"},"404":{"description":"Secret not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/settings":{"post":{"tags":["Projects"],"summary":"Update project settings","operationId":"update_project_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Project settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills":{"get":{"tags":["Agents"],"operationId":"list_skills","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSkillsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSkillRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/upload":{"post":{"tags":["Agents"],"summary":"Upload a skill with an archive (tar.gz) — project-scoped.","operationId":"upload_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/{slug}":{"get":{"tags":["Agents"],"operationId":"get_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSkillRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Skill deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/{slug}/archive":{"get":{"tags":["Agents"],"summary":"Download a skill's archive (tar.gz) — project-scoped.","operationId":"download_skill_archive","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill archive tar.gz","content":{"application/gzip":{}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found or has no archive"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/source-map-releases":{"get":{"tags":["source-maps"],"summary":"List all releases that have source maps for a project","operationId":"list_releases","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of releases","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/source-maps/{source_map_id}":{"delete":{"tags":["source-maps"],"summary":"Delete a specific source map by ID","operationId":"delete_source_map","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"source_map_id","in":"path","description":"Source map ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Source map deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Source map not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/static-bundles":{"get":{"tags":["Static Bundles"],"summary":"List static bundles for a project","operationId":"list_static_bundles","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of static bundles","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedStaticBundlesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/static-bundles/{bundle_id}":{"get":{"tags":["Static Bundles"],"summary":"Get details of a specific static bundle","operationId":"get_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"bundle_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Bundle details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaticBundleResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Static Bundles"],"summary":"Delete a static bundle","operationId":"delete_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"bundle_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Bundle deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/status":{"get":{"tags":["Status Page"],"summary":"Get status page overview","operationId":"get_status_overview","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved status overview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageOverview"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/unique-counts":{"get":{"tags":["Events"],"summary":"Get unique counts over time frame","operationId":"get_unique_counts","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric to count: 'sessions' (unique sessions), 'visitors' (unique visitors), 'returning_visitors' (visitors seen before the range), or 'page_views' (total page views) (default: 'sessions')","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UniqueCountsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/upload/static":{"post":{"tags":["Static Bundles"],"summary":"Upload a static bundle for later deployment","description":"Uploads a tar.gz or zip file containing static assets. The bundle can be\ndeployed later using the deploy/static endpoint.","operationId":"upload_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"201":{"description":"Bundle uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaticBundleResponse"}}}},"400":{"description":"Invalid request or unsupported format"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"413":{"description":"Bundle too large"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans":{"get":{"tags":["Vulnerability Scans"],"operationId":"list_project_scans","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of vulnerability scans","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScanResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Vulnerability Scans"],"operationId":"trigger_scan","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerScanRequest"}}},"required":true},"responses":{"202":{"description":"Scan triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerScanResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans/environments":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_latest_scans_per_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest scans per environment for current deployments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScanResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans/latest":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_latest_scan","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest scan for project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"No scans found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks":{"get":{"tags":["Webhooks"],"summary":"List all webhooks for a project","operationId":"list_webhooks","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of webhooks","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Webhooks"],"summary":"Create a new webhook","operationId":"create_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequestBody"}}},"required":true},"responses":{"201":{"description":"Webhook created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}":{"get":{"tags":["Webhooks"],"summary":"Get a specific webhook","operationId":"get_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Webhook details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Webhooks"],"summary":"Update a webhook","operationId":"update_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequestBody"}}},"required":true},"responses":{"200":{"description":"Webhook updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","operationId":"delete_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Webhook deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries":{"get":{"tags":["Webhook Deliveries"],"summary":"List webhook deliveries","operationId":"list_deliveries","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Number of deliveries to return (default: 50)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of deliveries","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries/{delivery_id}":{"get":{"tags":["Webhook Deliveries"],"summary":"Get a specific webhook delivery by ID","operationId":"get_delivery","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"delivery_id","in":"path","description":"Delivery ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Delivery details including full payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Delivery not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries/{delivery_id}/retry":{"post":{"tags":["Webhook Deliveries"],"summary":"Retry a failed delivery","operationId":"retry_delivery","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"delivery_id","in":"path","description":"Delivery ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Delivery retried","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Delivery not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/workflows/dry-run":{"post":{"tags":["Workflows"],"operationId":"workflow_dry_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDryRunRequest"}}},"required":true},"responses":{"202":{"description":"Ephemeral run created and queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Validation error (bad YAML, oversized payload, capped limits exceeded)"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/proxy-logs":{"get":{"tags":["Proxy Logs"],"summary":"Get proxy logs with optional filters and pagination","operationId":"get_proxy_logs","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"session_id","in":"query","description":"Filter by session ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"visitor_id","in":"query","description":"Filter by visitor ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering (ISO 8601 format).\n\n**Defaults to 1 hour before `end_date` (or before now) when omitted.**\nThe listing is always time-bounded: an unbounded query would have to\nconsider the entire retention window — 100M+ rows on a busy deployment —\nto return a single page. Pass an explicit `start_date` to widen the\nwindow, up to the configured retention horizon.\n\nThe maximum span between `start_date` and `end_date` is 7 days when\n`project_id` is omitted, or 30 days when a single `project_id` is set —\na project-scoped query is bounded by that project's own row count\nrather than the whole deployment's. A wider request is rejected with a\n400 naming the applicable cap.","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"end_date","in":"query","description":"End date for filtering (ISO 8601 format). Defaults to now.","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"method","in":"query","description":"Filter by HTTP method (GET, POST, etc.)","required":false,"schema":{"type":["string","null"]}},{"name":"host","in":"query","description":"Filter by host header","required":false,"schema":{"type":["string","null"]}},{"name":"path","in":"query","description":"Filter by path (supports partial match)","required":false,"schema":{"type":["string","null"]}},{"name":"client_ip","in":"query","description":"Filter by client IP address","required":false,"schema":{"type":["string","null"]}},{"name":"status_code","in":"query","description":"Filter by HTTP status code","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"response_time_min","in":"query","description":"Filter by minimum response time in ms","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"response_time_max","in":"query","description":"Filter by maximum response time in ms","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"routing_status","in":"query","description":"Filter by routing status (routed, no_project, error, pending)","required":false,"schema":{"type":["string","null"]}},{"name":"request_source","in":"query","description":"Filter by request source (proxy, api, console, cli)","required":false,"schema":{"type":["string","null"]}},{"name":"is_system_request","in":"query","description":"Filter by system request flag","required":false,"schema":{"type":["boolean","null"]}},{"name":"user_agent","in":"query","description":"Filter by user agent string (partial match)","required":false,"schema":{"type":["string","null"]}},{"name":"browser","in":"query","description":"Filter by browser name","required":false,"schema":{"type":["string","null"]}},{"name":"operating_system","in":"query","description":"Filter by operating system","required":false,"schema":{"type":["string","null"]}},{"name":"device_type","in":"query","description":"Filter by device type (mobile, desktop, tablet)","required":false,"schema":{"type":["string","null"]}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":["boolean","null"]}},{"name":"exclude_bots","in":"query","description":"When `true`, exclude rows flagged as bots while KEEPING rows whose\n`is_bot` is NULL (older rows without detection metadata). This is the\ntri-state complement of `is_bot=false`, which matches only rows\nexplicitly detected as non-bots. `false`/omitted is a no-op.","required":false,"schema":{"type":["boolean","null"]}},{"name":"bot_name","in":"query","description":"Filter by bot name","required":false,"schema":{"type":["string","null"]}},{"name":"ai_provider","in":"query","description":"Filter by AI provider (e.g. `OpenAI`, `Anthropic`, `Perplexity`). Matches\nthe canonical provider returned by the AI agent detector.","required":false,"schema":{"type":["string","null"]}},{"name":"ai_agent","in":"query","description":"Filter by AI agent name (e.g. `GPTBot`, `ChatGPT-User`). Equivalent to\nfiltering `bot_name` against a known AI taxonomy.","required":false,"schema":{"type":["string","null"]}},{"name":"is_ai_agent","in":"query","description":"When `true`, only return requests classified as known AI agents\n(regardless of provider/agent). Mutually compatible with the above.","required":false,"schema":{"type":["boolean","null"]}},{"name":"request_size_min","in":"query","description":"Filter by minimum request size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"request_size_max","in":"query","description":"Filter by maximum request size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"response_size_min","in":"query","description":"Filter by minimum response size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"response_size_max","in":"query","description":"Filter by maximum response size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"cache_status","in":"query","description":"Filter by cache status","required":false,"schema":{"type":["string","null"]}},{"name":"container_id","in":"query","description":"Filter by container ID","required":false,"schema":{"type":["string","null"]}},{"name":"upstream_host","in":"query","description":"Filter by upstream host","required":false,"schema":{"type":["string","null"]}},{"name":"has_error","in":"query","description":"Filter by presence of error message","required":false,"schema":{"type":["boolean","null"]}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"sort_by","in":"query","description":"Sort by field (default: timestamp)","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","description":"Sort order (asc or desc, default: desc)","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of proxy logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogsPaginatedResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/ai-agents/known":{"get":{"tags":["Proxy Logs"],"summary":"List every AI agent the detector knows how to classify.","description":"Returned in the same order as the internal taxonomy so the UI can use it as\na stable dropdown.","operationId":"list_known_ai_agents","responses":{"200":{"description":"Known AI agents","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnownAiAgentsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/request/{request_id}":{"get":{"tags":["Proxy Logs"],"summary":"Get a proxy log by request ID (for tracing)","operationId":"get_proxy_log_by_request_id","parameters":[{"name":"request_id","in":"path","description":"Request ID from pingora","required":true,"schema":{"type":"string"}},{"name":"timestamp","in":"query","description":"Event time of the log row (ISO 8601). When provided, the lookup is\nbounded to the hypertable chunks around this instant instead of\nscanning (and decompressing) the whole retention window. The list\nendpoint already returns this value per row — always pass it when\nnavigating from a list.","required":false,"schema":{"type":["string","null"],"format":"date-time"}}],"responses":{"200":{"description":"Proxy log found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Proxy log not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agent-pages":{"get":{"tags":["Proxy Logs"],"summary":"Get the top pages accessed by a specific AI agent over a time window.","description":"Returns page paths ranked by request count, scoped to a single canonical\nagent name (e.g. `ChatGPT-User`). Use `GET /proxy-logs/ai-agents/known` to\nlist all valid agent names. Unknown agent names return an empty items array.","operationId":"get_ai_agent_pages","parameters":[{"name":"agent","in":"query","description":"Canonical agent name to filter by (e.g. `ChatGPT-User`, `ClaudeBot`).\nMust be a name returned by `GET /proxy-logs/ai-agents/known`.","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Filter by project ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"Pages breakdown for the requested agent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentPagesResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agents":{"get":{"tags":["Proxy Logs"],"summary":"Get the per-AI-agent breakdown for a project over a time window.","operationId":"get_ai_agent_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI agent breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agents/timeline":{"get":{"tags":["Proxy Logs"],"summary":"Time-bucketed AI-agent request volume, split by provider or agent.","description":"Powers the \"AI agents over time\" stacked chart. Same data source as the AI\nagent breakdown (request logs), just bucketed.","operationId":"get_ai_agent_timeline","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"group_by","in":"query","description":"Grouping dimension: `provider` (default) or `agent`.","required":false,"schema":{"type":["string","null"]},"example":"provider"},{"name":"bucket","in":"query","description":"Bucket interval override (e.g. `1 hour`, `1 day`). Auto-selected from the\nwindow width when omitted.","required":false,"schema":{"type":["string","null"]},"example":"1 hour"}],"responses":{"200":{"description":"AI agent timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentTimelineResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-pages":{"get":{"tags":["Proxy Logs"],"summary":"Get the top pages crawled by AI agents over a time window.","operationId":"get_ai_page_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI page breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiPageBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-status":{"get":{"tags":["Proxy Logs"],"summary":"HTTP status-class breakdown for AI-agent traffic — are bots being served\n(2xx) or hitting broken/blocked pages (4xx/5xx)?","operationId":"get_ai_status_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI status breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiStatusBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/projects-health":{"get":{"tags":["Proxy Logs"],"summary":"Get health summaries for multiple projects (last 1 hour)","operationId":"get_projects_health","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Optional start time (ISO 8601). Defaults to `end_time - 1h`.","required":false,"schema":{"type":["string","null"]},"example":"2025-10-23T00:00:00Z"},{"name":"end_time","in":"query","description":"Optional end time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2025-10-23T23:59:59Z"},{"name":"is_bot","in":"query","description":"Filter by bot detection. Pass `false` to exclude bots, `true` for bots only.","required":false,"schema":{"type":["boolean","null"]}}],"responses":{"200":{"description":"Health summaries per project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectsHealthResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/time-buckets":{"get":{"tags":["Proxy Logs"],"summary":"Get time-bucketed statistics with optional filters","operationId":"get_time_bucket_stats","parameters":[{"name":"start_time","in":"query","description":"Start time (ISO 8601 format)","required":true,"schema":{"type":"string"},"example":"2025-10-23T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601 format)","required":true,"schema":{"type":"string"},"example":"2025-10-23T23:59:59Z"},{"name":"bucket_interval","in":"query","description":"Bucket interval (e.g., \"1 hour\", \"1 day\", \"5 minutes\")","required":false,"schema":{"type":"string"}},{"name":"method","in":"query","description":"Filter by HTTP method","required":false,"schema":{"type":"string"}},{"name":"client_ip","in":"query","description":"Filter by client IP","required":false,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"host","in":"query","description":"Filter by host","required":false,"schema":{"type":"string"}},{"name":"status_code","in":"query","description":"Filter by status code","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"status_code_class","in":"query","description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")","required":false,"schema":{"type":"string"}},{"name":"routing_status","in":"query","description":"Filter by routing status","required":false,"schema":{"type":"string"}},{"name":"request_source","in":"query","description":"Filter by request source","required":false,"schema":{"type":"string"}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":"boolean"}},{"name":"device_type","in":"query","description":"Filter by device type","required":false,"schema":{"type":"string"}},{"name":"has_project","in":"query","description":"When true, only count requests that matched a project\n(project_id IS NOT NULL). Makes chart totals line up with the\nper-project health cards.","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Time-bucketed statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBucketStatsResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/today":{"get":{"tags":["Proxy Logs"],"summary":"Get today's request count with optional filters","operationId":"get_today_stats","parameters":[{"name":"method","in":"query","description":"Filter by HTTP method","required":false,"schema":{"type":["string","null"]}},{"name":"client_ip","in":"query","description":"Filter by client IP","required":false,"schema":{"type":["string","null"]}},{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"host","in":"query","description":"Filter by host","required":false,"schema":{"type":["string","null"]}},{"name":"status_code","in":"query","description":"Filter by status code","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"status_code_class","in":"query","description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")","required":false,"schema":{"type":["string","null"]}},{"name":"routing_status","in":"query","description":"Filter by routing status","required":false,"schema":{"type":["string","null"]}},{"name":"request_source","in":"query","description":"Filter by request source","required":false,"schema":{"type":["string","null"]}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":["boolean","null"]}},{"name":"device_type","in":"query","description":"Filter by device type","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Today's request count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TodayStatsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/{id}":{"get":{"tags":["Proxy Logs"],"summary":"Get a single proxy log by ID","operationId":"get_proxy_log_by_id","parameters":[{"name":"id","in":"path","description":"Proxy log ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"timestamp","in":"query","description":"Event time of the log row (ISO 8601). When provided, the lookup is\nbounded to the hypertable chunks around this instant instead of\nscanning (and decompressing) the whole retention window. The list\nendpoint already returns this value per row — always pass it when\nnavigating from a list.","required":false,"schema":{"type":["string","null"],"format":"date-time"}}],"responses":{"200":{"description":"Proxy log found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Proxy log not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/repositories":{"get":{"tags":["Git Providers"],"summary":"List synced repositories with advanced filtering","description":"Lists repositories that have been synced to the database with filtering options.\nThis provides fast access to repository metadata with filtering by connection, search, and other criteria.","operationId":"list_synced_repositories","parameters":[{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, watchers, size, issues)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}},{"name":"git_provider_connection_id","in":"query","description":"Filter by git provider connection ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of synced repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}":{"get":{"tags":["Git Providers"],"summary":"Get repository by owner and name from any connection","operationId":"get_repository_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Optional specific connection ID to search","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Repository found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}/all":{"get":{"tags":["Git Providers"],"summary":"Get all repositories with same owner/name from all git providers","operationId":"get_all_repositories_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repositories found from all providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RepositoryResponse"}}}}},"404":{"description":"No repositories found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}/preset":{"get":{"tags":["Git Providers"],"summary":"Get repository preset by owner and name","operationId":"get_repository_preset_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"branch","in":"query","description":"Git branch to check (defaults to repository's default branch)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository preset calculated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryPresetResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{repo}/branches":{"get":{"tags":["Repositories"],"summary":"Get repository branches","operationId":"get_repository_branches","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Git provider connection ID (required when multiple connections have the same repo)","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{repo}/tags":{"get":{"tags":["Repositories"],"summary":"Get repository tags","operationId":"get_repository_tags","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Git provider connection ID (required when multiple connections have the same repo)","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Fresh tag lookup rate limit exceeded"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{repository_id}/preset/live":{"get":{"tags":["Git Providers"],"operationId":"get_repository_preset_live","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"branch","in":"query","description":"Git branch to check (defaults to repository's default branch)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository presets calculated successfully - includes root preset and projects in subdirectories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryPresetResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"The git provider rejected the stored credential - the connection must be re-authorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}":{"get":{"tags":["Git Providers"],"summary":"Get repository by ID","operationId":"get_repository_by_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Repository found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/branches":{"get":{"tags":["Repositories"],"summary":"Get repository branches by repository ID","operationId":"get_branches_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/commits":{"get":{"tags":["Repositories"],"summary":"List recent commits for a repository branch","operationId":"list_commits_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"branch","in":"query","description":"Branch name to list commits for","required":true,"schema":{"type":"string"}},{"name":"per_page","in":"query","description":"Number of commits to return (default: 20, max: 100)","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}}],"responses":{"200":{"description":"List of commits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/commits/{commit_sha}":{"get":{"tags":["Repositories"],"summary":"Check if a commit exists in a repository","operationId":"check_commit_exists","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"commit_sha","in":"path","description":"Commit SHA to check","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Commit existence check result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitExistsResponse"}}}},"400":{"description":"Invalid commit SHA"},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Commit lookup rate limit exceeded"},"500":{"description":"Internal server error"},"502":{"description":"Git provider request failed"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/tags":{"get":{"tags":["Repositories"],"summary":"Get repository tags by repository ID","operationId":"get_tags_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Fresh tag lookup rate limit exceeded"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/restore-runs/{id}":{"get":{"tags":["Restore"],"operationId":"get_restore_run","parameters":[{"name":"id","in":"path","description":"Restore run id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Restore run progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreRunView"}}}},"404":{"description":"Restore run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/events":{"get":{"tags":["Revenue"],"summary":"Org-wide revenue events across every project. Powers the revenue\ntransactions page. Supports filtering by project, date range, and\nevent type.","operationId":"revenue_global_events","parameters":[{"name":"project_id","in":"query","description":"Filter to a single project","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"from","in":"query","description":"Lower bound (inclusive), ISO-8601","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"Upper bound (inclusive), ISO-8601","required":false,"schema":{"type":"string"}},{"name":"event_types","in":"query","description":"Comma-separated event types (e.g. `invoice.paid,charge.succeeded`)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max rows, default 100, max 500","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GlobalRecentEventResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/metrics/global-mrr":{"get":{"tags":["Revenue"],"summary":"Org-wide MRR total, summed across every project in the install.\nPowers the single-number MRR card on the main dashboard.","operationId":"revenue_metrics_global_mrr","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalMrrResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/metrics/global-summary":{"get":{"tags":["Revenue"],"summary":"Org-wide revenue summary: MRR, paid cash (30d + all-time), refunds,\nactive subscriptions/customers, and transaction count. Powers the\nheader on the Revenue transactions page.","operationId":"revenue_metrics_global_summary","parameters":[{"name":"currency","in":"query","description":"ISO-4217 currency code, default USD","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalRevenueSummaryResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/providers":{"get":{"tags":["Revenue"],"summary":"List registered providers (what the UI needs to render the \"Connect\"\ndropdown + its wizard instructions).","operationId":"revenue_list_providers","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderDescriptor"}}}}}},"security":[{"bearer_auth":[]}]}},"/session-replays":{"get":{"tags":["Analytics"],"summary":"Get session replays for a project","operationId":"get_project_session_replays","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Session replays retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetProjectSessionReplaysResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/sessions/{session_id}/events":{"get":{"tags":["Events"],"summary":"Get events for a specific session","operationId":"get_session_events","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsSessionEventsResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings":{"get":{"tags":["Settings"],"summary":"Get application settings","operationId":"get_settings","responses":{"200":{"description":"Application settings with masked sensitive fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppSettingsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Settings"],"summary":"Update application settings","operationId":"update_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppSettings"}}},"required":true},"responses":{"200":{"description":"Settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"400":{"description":"Bad request - invalid settings"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/agent-token":{"post":{"tags":["Agents"],"summary":"Save an encrypted AI provider token for use in sandbox containers.","operationId":"save_agent_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAgentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token encrypted and persisted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAgentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Encryption or database error"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers":{"get":{"tags":["Agents"],"summary":"List the AI provider catalog. Includes per-provider \"is a credential\nconfigured?\" so the settings UI can render configured/not-configured\nbadges without leaking the encrypted credential.","operationId":"list_ai_providers","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderCatalogResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}":{"patch":{"tags":["Agents"],"summary":"Update provider-scoped settings without touching the saved credential.\nToday that means just `default_model`; future per-provider settings\n(base URL overrides, request headers, etc.) can land here too without\nchanging the shape of `save_credential`.","operationId":"update_ai_provider","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiProviderRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiProviderResponse"}}}},"400":{"description":"Unknown provider"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}/activate":{"post":{"tags":["Agents"],"summary":"Activate a provider as the platform-wide default. Refuses to activate a\nprovider that doesn't have a credential saved yet — the UI enforces the\nsame rule on the button, but we re-check server-side so a stale tab\ncan't bypass it.","operationId":"activate_ai_provider","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivateProviderResponse"}}}},"400":{"description":"Provider not configured"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}/credential":{"post":{"tags":["Agents"],"summary":"Save (or replace) a provider's credential. The credential is encrypted\nwith `EncryptionService` and stored inside\n`agent_sandbox.providers[provider_id].credentials_encrypted`.","description":"The plaintext shape depends on the flavor's `credential_format`:\n - `ApiKey` / `OauthToken`: the key/token string.\n - `ConfigFile`: the full file body (e.g. OpenCode's `auth.json`).","operationId":"save_ai_provider_credential","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveCredentialRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveCredentialResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/disk-status":{"get":{"tags":["Settings"],"summary":"Get current disk usage for the control-plane server","description":"Returns live disk usage for the monitored path along with any disks that\nmeet or exceed the configured alert threshold. Read-only — does not send\nnotifications. Used by the dashboard to surface a low-disk-space warning.","operationId":"get_disk_status","responses":{"200":{"description":"Current disk usage and threshold alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiskSpaceCheckResult"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/enrollment-tokens":{"get":{"tags":["Settings"],"summary":"List currently-valid node enrollment tokens (hashes elided).","operationId":"list_enrollment_tokens","responses":{"200":{"description":"Active enrollment tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollmentTokenListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Settings"],"summary":"Mint a short-lived, single-use node enrollment token.","operationId":"mint_enrollment_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintEnrollmentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Enrollment token minted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintEnrollmentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/enrollment-tokens/{id}":{"delete":{"tags":["Settings"],"summary":"Revoke a node enrollment token by id.","operationId":"revoke_enrollment_token","parameters":[{"name":"id","in":"path","description":"Enrollment token id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Enrollment token revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Enrollment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token":{"delete":{"tags":["Settings"],"summary":"Revoke the current join token","description":"Removes the stored join token hash, allowing any node to register\n(if no other authentication is in place).","operationId":"revoke_join_token","responses":{"200":{"description":"Join token revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token/generate":{"post":{"tags":["Settings"],"summary":"Generate a new join token for multi-node cluster registration","description":"Creates a random 32-byte hex token, stores the SHA-256 hash in settings,\nand returns the plaintext exactly once. If a token already exists, it is replaced.","operationId":"generate_join_token","responses":{"200":{"description":"Join token generated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateJoinTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token/status":{"get":{"tags":["Settings"],"summary":"Check whether a join token is currently configured","operationId":"get_join_token_status","responses":{"200":{"description":"Join token status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinTokenStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers":{"get":{"tags":["Agents"],"operationId":"list_global_mcps","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMcpsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_global_mcp","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMcpRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers/{slug}":{"get":{"tags":["Agents"],"operationId":"get_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMcpRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"MCP server deleted"},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers/{slug}/config/{field}":{"get":{"tags":["Agents"],"operationId":"reveal_global_mcp_config","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}},{"name":"field","in":"path","description":"Sensitive field path, such as url or env.API_TOKEN","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveMcpConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"401":{"description":"Unauthorized"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"MCP server or field not found"},"500":{"description":"Configuration read or audit failed"}},"security":[{"bearer_auth":[]}]}},"/settings/routes/refresh":{"post":{"tags":["Settings"],"summary":"Manually refresh the proxy route table","description":"Reloads all routes from the database into the in-memory proxy cache.\nUseful as a workaround when routes are out of sync.","operationId":"refresh_route_table","responses":{"200":{"description":"Route table refreshed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteRefreshResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/sandbox-rebuild":{"post":{"tags":["Agents"],"operationId":"rebuild_sandbox_image","responses":{"200":{"description":"Server-Sent Events stream of rebuild progress; final event `{\"type\":\"done\",\"success\":bool,...}`","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/sandbox-status":{"get":{"tags":["Agents"],"operationId":"get_global_sandbox_status","responses":{"200":{"description":"Global sandbox readiness for the settings page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/secrets":{"get":{"tags":["Secrets"],"operationId":"list_secrets","responses":{"200":{"description":"List of global agent secrets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSecretsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Secrets"],"operationId":"upsert_secret","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertSecretRequest"}}},"required":true},"responses":{"201":{"description":"Secret created/updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/secrets/{name}":{"delete":{"tags":["Secrets"],"operationId":"delete_secret","parameters":[{"name":"name","in":"path","description":"Secret name","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Secret deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Secret not found"}},"security":[{"bearer_auth":[]}]}},"/settings/skills":{"get":{"tags":["Agents"],"operationId":"list_global_skills","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSkillsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_global_skill","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSkillRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/upload":{"post":{"tags":["Agents"],"summary":"Upload a skill with an archive (tar.gz) — global.","operationId":"upload_global_skill","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/{slug}":{"get":{"tags":["Agents"],"operationId":"get_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSkillRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Skill deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/{slug}/archive":{"get":{"tags":["Agents"],"summary":"Download a skill's archive (tar.gz) — global.","operationId":"download_global_skill_archive","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill archive tar.gz","content":{"application/gzip":{}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found or has no archive"}},"security":[{"bearer_auth":[]}]}},"/settings/update-status":{"get":{"tags":["Settings"],"summary":"Report whether a newer temps release is available for this install.","operationId":"get_update_status","responses":{"200":{"description":"Release update status for this install","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/templates":{"get":{"tags":["Templates"],"summary":"List all available templates","description":"Returns a list of all public templates, optionally filtered by tag or featured status.","operationId":"list_project_templates","parameters":[{"name":"tag","in":"query","description":"Filter templates by tag","required":false,"schema":{"type":"string"}},{"name":"featured","in":"query","description":"Only return featured templates","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of templates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTemplatesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/templates/tags":{"get":{"tags":["Templates"],"summary":"List all available template tags","description":"Returns a list of all unique tags used by public templates.","operationId":"list_project_template_tags","responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTagsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/templates/{slug}":{"get":{"tags":["Templates"],"summary":"Get a specific template by slug","description":"Returns detailed information about a single template.","operationId":"get_project_template","parameters":[{"name":"slug","in":"path","description":"Template slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Template not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/user/me":{"get":{"tags":["Authentication"],"operationId":"get_current_user","responses":{"200":{"description":"Successfully retrieved user information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/users":{"get":{"tags":["Users"],"operationId":"list_users","parameters":[{"name":"include_deleted","in":"query","description":"Include deleted users in the response","required":true,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List all users with their roles","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}}},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Users"],"summary":"Create a new user with roles","operationId":"create_user","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRequest"}}},"required":true},"responses":{"201":{"description":"User created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me":{"patch":{"tags":["Users"],"summary":"Update current user's information","operationId":"update_self","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSelfRequest"}}},"required":true},"responses":{"200":{"description":"User updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa":{"delete":{"tags":["Users"],"operationId":"disable_mfa","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableMfaRequest"}}},"required":true},"responses":{"204":{"description":"MFA disabled"},"400":{"description":"Invalid verification code"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa/setup":{"post":{"tags":["Users"],"operationId":"setup_mfa","responses":{"200":{"description":"MFA setup data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaSetupResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa/verify":{"post":{"tags":["Users"],"operationId":"verify_and_enable_mfa","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyMfaRequest"}}},"required":true},"responses":{"204":{"description":"MFA verified and enabled"},"400":{"description":"Invalid code"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/password":{"post":{"tags":["Users"],"operationId":"change_password_self","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"204":{"description":"Password updated"},"400":{"description":"Validation error (weak password, same as current, MFA missing)"},"401":{"description":"Current password incorrect or MFA code invalid"},"403":{"description":"Account has no password set (SSO only)"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}":{"delete":{"tags":["Users"],"summary":"Delete a user","operationId":"delete_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"User deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Cannot delete yourself or non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Users"],"summary":"Update user information (admin only)","operationId":"update_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequest"}}},"required":true},"responses":{"200":{"description":"User updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/restore":{"post":{"tags":["Users"],"operationId":"restore_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"User restored successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"User is not deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/roles":{"post":{"tags":["Users"],"operationId":"assign_role","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignRoleRequest"}}},"required":true},"responses":{"200":{"description":"Role assigned successfully"},"400":{"description":"Invalid role type"},"401":{"description":"Unauthorized"},"403":{"description":"Admin role required or self-modification forbidden"},"404":{"description":"User or role not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/roles/{role_type}":{"delete":{"tags":["Users"],"operationId":"remove_role","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"role_type","in":"path","description":"Role type to remove","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Role removed successfully"},"400":{"description":"Invalid role type"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Cannot modify own roles or non-admin attempt"},"404":{"description":"User or role not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes":{"get":{"tags":["Sandboxes"],"operationId":"list_sandboxes","parameters":[{"name":"page","in":"query","description":"Page (1-indexed)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default 20, max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List sandboxes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSandboxesResponse"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Sandboxes"],"operationId":"create_sandbox","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSandboxBody"}}},"required":true},"responses":{"201":{"description":"Sandbox created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/rootfs":{"get":{"tags":["Sandboxes"],"summary":"Inspect rootfs storage: the Firecracker digest-keyed cache (with which\nsandboxes reference each entry) and per-VM disks. Empty on Docker-only\nhosts. Admin/read scope — this exposes host storage layout.","operationId":"rootfs_report","responses":{"200":{"description":"Rootfs storage report"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/rootfs/gc":{"post":{"tags":["Sandboxes"],"summary":"Reclaim rootfs cache entries not backing any live sandbox. Idempotent;\nsafe to call any time (live VMs hold their own per-VM disks).","operationId":"rootfs_gc","responses":{"200":{"description":"Reclaimed cache entries"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}":{"get":{"tags":["Sandboxes"],"operationId":"get_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd":{"post":{"tags":["Sandboxes"],"summary":"Run a command inside the sandbox (`@vercel/sandbox`-compatible).","description":"`wait=false` (default) returns `{ command: {..., exitCode: null} }`\nimmediately once the background task is spawned.\n\n`wait=true` streams `application/x-ndjson`: the first line is the\nrunning envelope, the second is the finished envelope with `exitCode`.","operationId":"cmd","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdBody"}}},"required":true},"responses":{"200":{"description":"Command started (wait=false) or finished (wait=true)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd/{cmd_id}":{"get":{"tags":["Sandboxes"],"operationId":"get_cmd","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Command snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd/{cmd_id}/logs":{"get":{"tags":["Sandboxes"],"summary":"Stream a command's stdout/stderr as `application/x-ndjson`\n(`@vercel/sandbox`-compatible). Each line is either\n`{stream:\"stdout\"|\"stderr\", data:\"...\"}` or\n`{stream:\"error\", data:{code, message}}`.","operationId":"cmd_logs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"NDJSON stream of log events"},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/destroy":{"post":{"tags":["Sandboxes"],"operationId":"destroy_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Sandbox destroyed (alias for `/stop` with an explicit verb)"},"404":{"description":"Not found"},"409":{"description":"Sandbox belongs to an active agent run — stop the run instead"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/domain":{"get":{"tags":["Sandboxes"],"operationId":"domain","parameters":[{"name":"port","in":"query","description":"Port inside the sandbox (1..=65535)","required":true,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Preview URL for the port","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxDomainResponse"}}}},"400":{"description":"Invalid port"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/events":{"get":{"tags":["Sandboxes"],"summary":"The operations timeline for a sandbox (lifecycle events only — never\nshell/exec activity), newest first.","operationId":"list_events","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Operations timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxEventsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/exec":{"post":{"tags":["Sandboxes"],"operationId":"exec","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecBody"}}},"required":true},"responses":{"200":{"description":"Command finished (non-zero exit is NOT an error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/exec-detached":{"post":{"tags":["Sandboxes"],"operationId":"exec_detached","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecBody"}}},"required":true},"responses":{"202":{"description":"Command accepted; poll /jobs/{job_id}","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecDetachedResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/extend-timeout":{"post":{"tags":["Sandboxes"],"operationId":"extend_timeout","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtendTimeoutBody"}}},"required":true},"responses":{"200":{"description":"Timeout extended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/mkdir":{"post":{"tags":["Sandboxes"],"operationId":"mkdir","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MkdirBody"}}},"required":true},"responses":{"204":{"description":"Directory created (or already existed)"},"400":{"description":"Validation error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/read":{"get":{"tags":["Sandboxes"],"operationId":"read_file","parameters":[{"name":"path","in":"query","description":"Absolute file path inside the sandbox","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File contents (base64)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadFileResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Sandbox or file not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/stat":{"get":{"tags":["Sandboxes"],"operationId":"stat_path","parameters":[{"name":"path","in":"query","description":"Absolute path inside the sandbox","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Stat info (exists=false when missing — not an error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatResponse"}}}},"400":{"description":"Validation error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/write":{"post":{"tags":["Sandboxes"],"summary":"Write a file into the sandbox. Accepts two body shapes — the SDK\npicks one based on `Content-Type`:","description":"- **`application/json`** (temps-native): `{path, contents_b64, mode}`\n — one file, base64-encoded.\n- **`application/gzip`** (`@vercel/sandbox`): a gzipped tarball of\n one-or-more entries, with the target extract dir carried in the\n `x-cwd` header. The SDK's `writeFile` and `writeFiles` both post\n here; they differ only in how many entries the tarball contains.\n\nWhy merge them on one route: the SDK is hardcoded to\n`POST /fs/write`, so splitting tar uploads onto a separate path would\nforce us to break SDK compat. Instead we dispatch on Content-Type,\npreserve JSON for native callers, and add tar for SDK callers.","operationId":"write_file","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFileBody"}}},"required":true},"responses":{"204":{"description":"File(s) written"},"400":{"description":"Validation error or invalid base64"},"404":{"description":"Sandbox not found"},"415":{"description":"Unsupported Content-Type (expected application/json or application/gzip)"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/write-batch":{"post":{"tags":["Sandboxes"],"summary":"Batch-write multiple files in a single request. Mirrors\n`@vercel/sandbox` `writeFiles()`. Semantics are fail-fast: if any\nfile errors, previously-written entries are left in place and the\nerror describes which file broke.","operationId":"write_files","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFilesBody"}}},"required":true},"responses":{"200":{"description":"All files written","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFilesResponse"}}}},"400":{"description":"Validation error or invalid base64"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs":{"get":{"tags":["Sandboxes"],"operationId":"list_jobs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Detached jobs for this sandbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListJobsResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}":{"get":{"tags":["Sandboxes"],"operationId":"job_status","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusResponse"}}}},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}/kill":{"post":{"tags":["Sandboxes"],"summary":"Terminate a detached job. Aborts the server-side tracking task and\nsends SIGTERM (or SIGKILL if `force=true`) to any matching processes\ninside the sandbox container. Returns 204 on success; 404 if the\nsandbox or job is unknown.","operationId":"kill_job","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KillJobBody"}}},"required":true},"responses":{"204":{"description":"Job killed"},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}/logs":{"get":{"tags":["Sandboxes"],"summary":"SSE endpoint streaming each stdout/stderr line from a detached job\nas it's produced. Mirrors the `Command.logs()` async iterator shape\non `@vercel/sandbox` — events carry `{ stream, data }`.","description":"Late subscribers only see events produced after they connect. The\nJobState snapshot (`GET /jobs/{job_id}`) covers the history.\n\nA \"done\" sentinel event fires when the broadcast channel closes\n(the exec task has exited and dropped the sender), signalling\ncallers they can stop reading.","operationId":"job_logs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"SSE stream of log events"},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/pause":{"post":{"tags":["Sandboxes"],"operationId":"pause_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox paused (container stopped, state preserved)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is in an incompatible state (e.g. already destroyed)"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/preview-password":{"put":{"tags":["Sandboxes"],"operationId":"set_preview_password","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPreviewPasswordBody"}}},"required":true},"responses":{"200":{"description":"Preview password set or rotated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPreviewPasswordResponse"}}}},"400":{"description":"Password too short or too long"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Sandboxes"],"operationId":"clear_preview_password","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Preview password removed (sandbox is now URL-only protected)"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/resize":{"post":{"tags":["Sandboxes"],"summary":"Grow a Firecracker sandbox's root disk. Offline resize — the VM reboots\n(filesystem/data persist) rather than resizing fully live.","operationId":"resize_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResizeSandboxBody"}}},"required":true},"responses":{"200":{"description":"Resized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Invalid size or unsupported backend"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/restart":{"post":{"tags":["Sandboxes"],"operationId":"restart_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox container restarted in place","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is stopped (use /resume) or already destroyed"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/resume":{"post":{"tags":["Sandboxes"],"operationId":"resume_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox resumed; expires_at refreshed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is not in a resumable state"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/source":{"post":{"tags":["Sandboxes"],"operationId":"source_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceBody"}}},"required":true},"responses":{"200":{"description":"Source content seeded into the sandbox work dir","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error (embedded creds, conflicting fields, etc.)"},"404":{"description":"Sandbox not found"},"409":{"description":"Sandbox is not running"},"500":{"description":"Source seed failed inside sandbox"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/stop":{"post":{"tags":["Sandboxes"],"operationId":"stop_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Sandbox stopped and destroyed"},"404":{"description":"Not found"},"409":{"description":"Sandbox belongs to an active agent run — stop the run instead"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/{cmd_id}/kill":{"post":{"tags":["Sandboxes"],"summary":"Kill a running command (`@vercel/sandbox`-compatible). The SDK\ncalls `POST /v1/sandboxes/{id}/{cmdId}/kill` — note the path has the\ncommand ID directly under the sandbox, NOT under `/jobs/` or `/cmd/`.","operationId":"cmd_kill","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdKillBody"}}}},"responses":{"200":{"description":"Command killed; returns final snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays":{"get":{"tags":["Analytics"],"summary":"Get session replays for a visitor","operationId":"get_visitor_sessions","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Session replays retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVisitorSessionsResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}":{"get":{"tags":["Analytics"],"summary":"Get session replay data with visitor info (without events)","operationId":"get_session_replay","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Session replay retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSessionReplayResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Analytics"],"summary":"Delete a session replay","operationId":"delete_session_replay","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Session replay deleted successfully"},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}/duration":{"put":{"tags":["Analytics"],"summary":"Update session duration","operationId":"update_session_duration","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionDurationRequest"}}},"required":true},"responses":{"200":{"description":"Session duration updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionDurationResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}/events":{"get":{"tags":["Analytics"],"summary":"Get session replay events (with session and visitor metadata)","operationId":"get_session_replay_events","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Session replay with events retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayWithEventsDto"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Analytics"],"summary":"Add events to an existing session","operationId":"add_events","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsRequest"}}},"required":true},"responses":{"200":{"description":"Events added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/vulnerability-scans/{scan_id}":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Scan details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Vulnerability Scans"],"operationId":"delete_scan","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Scan deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/vulnerability-scans/{scan_id}/vulnerabilities":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan_vulnerabilities","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"severity","in":"query","description":"Filter by severity (CRITICAL, HIGH, MEDIUM, LOW)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of vulnerabilities","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VulnerabilityResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/webhook-event-types":{"get":{"tags":["Webhooks"],"summary":"List available event types","operationId":"list_event_types","responses":{"200":{"description":"List of available event types","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTypeResponse"}}}}}}}},"/weekly-digest/trigger":{"post":{"tags":["Notification Preferences"],"summary":"Trigger weekly digest generation manually","operationId":"trigger_weekly_digest","responses":{"200":{"description":"Weekly digest triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerDigestResponse"}}}},"500":{"description":"Failed to generate digest"}},"security":[{"bearer_auth":[]}]}},"/x/plugins":{"get":{"tags":["External Plugins"],"summary":"List all running external plugins and their manifests.","description":"Requires only a valid session/token (no specific permission) since the\nmanifest drives sidebar navigation rendering for every authenticated\nuser, not just admins.","operationId":"list_external_plugins","responses":{"200":{"description":"List of all running external plugins","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PluginManifest"}}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/x/plugins/reload":{"post":{"tags":["External Plugins"],"summary":"Reload all external plugins.","description":"Stops all running plugin processes, re-scans the plugins directory,\nstarts any discovered binaries, and hot-swaps the proxy router so new\nand removed plugins take effect immediately without a server restart.\n\nRequires `SystemAdmin` permission.","operationId":"reload_plugins","responses":{"200":{"description":"Plugins reloaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReloadResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/{project_id}/envelope/":{"post":{"tags":["sentry-ingestor"],"summary":"Ingest a Sentry envelope (binary payload)","operationId":"ingest_sentry_envelope","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"Sentry envelope as binary data","content":{"application/octet-stream":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Envelope ingested"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"413":{"description":"Request body too large (exceeds 2 MiB)"}}}},"/{project_id}/store/":{"post":{"tags":["sentry-ingestor"],"summary":"Ingest a Sentry event (JSON payload)","operationId":"ingest_sentry_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryEventRequest"}}},"required":true},"responses":{"200":{"description":"Event ingested","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryEventResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"413":{"description":"Request body too large (exceeds 2 MiB)"}}}},"audit/logs":{"get":{"tags":["Audit Logs"],"summary":"List audit logs with optional filtering","operationId":"list_audit_logs","parameters":[{"name":"operation_type","in":"query","description":"Filter logs by operation type (omit for all)","required":false,"schema":{"type":"string"},"example":"user.login"},{"name":"user_id","in":"query","description":"Filter logs by user ID (omit for all users)","required":false,"schema":{"type":"integer","format":"int32"},"example":1},{"name":"from","in":"query","description":"Start timestamp (milliseconds since epoch)","required":false,"schema":{"type":"string","format":"date-time"},"example":1},{"name":"to","in":"query","description":"End timestamp (milliseconds since epoch)","required":false,"schema":{"type":"string","format":"date-time"},"example":1},{"name":"limit","in":"query","description":"Maximum number of logs to return","required":false,"schema":{"type":"integer","format":"int32"},"example":100},{"name":"offset","in":"query","description":"Number of logs to skip","required":false,"schema":{"type":"integer","format":"int32"},"example":0}],"responses":{"200":{"description":"List of audit logs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuditLogResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"api_key":[]}]}},"audit/logs/{id}":{"get":{"tags":["Audit Logs"],"summary":"Get a specific audit log entry by ID","operationId":"get_audit_log","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Audit log details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Audit log not found"},"500":{"description":"Internal server error"}},"security":[{"api_key":[]}]}}},"components":{"schemas":{"AcmeOrderResponse":{"type":"object","required":["id","order_url","domain_id","email","status","identifiers","created_at","updated_at"],"properties":{"authorizations":{},"certificate_url":{"type":["string","null"]},"challenge_validation":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeValidationStatus","description":"Live challenge validation status fetched from Let's Encrypt"}]},"created_at":{"type":"integer","format":"int64"},"domain_id":{"type":"integer","format":"int32"},"email":{"type":"string"},"error":{"type":["string","null"]},"error_type":{"type":["string","null"]},"expires_at":{"type":["integer","null"],"format":"int64"},"finalize_url":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"identifiers":{},"order_url":{"type":"string"},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"ActivateProviderResponse":{"type":"object","required":["default_provider"],"properties":{"default_provider":{"type":"string"}}},"ActiveVisitor":{"type":"object","required":["session_id","session_start","last_activity","page_count","event_count","duration_seconds","is_active"],"properties":{"current_page":{"type":["string","null"]},"duration_seconds":{"type":"integer","format":"int64"},"event_count":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_activity":{"type":"string"},"page_count":{"type":"integer","format":"int32"},"session_id":{"type":"string"},"session_start":{"type":"string"},"visitor_id":{"type":["string","null"]}}},"ActiveVisitorsQuery":{"type":"object","properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"}}},"ActiveVisitorsResponse":{"type":"object","required":["active_visitors","window_minutes"],"properties":{"active_visitors":{"type":"integer","format":"int64"},"window_minutes":{"type":"integer","format":"int32"}}},"ActivityDay":{"type":"object","description":"Daily activity count for a single day","required":["date","count","level"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of deployments on this day"},"date":{"type":"string","description":"Date in YYYY-MM-DD format","example":"2024-06-15"},"level":{"type":"integer","format":"int32","description":"Intensity level (0-4) for visualization\n0: No activity, 1: Low (1-2), 2: Medium (3-5), 3: High (6-10), 4: Very High (11+)","example":2}}},"ActivityEvent":{"type":"object","description":"A single activity event for the real-time activity feed","required":["id","timestamp","event_type","page_path","is_crawler"],"properties":{"browser":{"type":["string","null"],"description":"Browser"},"city":{"type":["string","null"],"description":"Visitor's city (from ip_geolocations)"},"country":{"type":["string","null"],"description":"Visitor's country (from ip_geolocations)"},"country_code":{"type":["string","null"],"description":"Visitor's country code (from ip_geolocations)"},"device_type":{"type":["string","null"],"description":"Device type"},"event_name":{"type":["string","null"],"description":"Event name (for custom events)"},"event_type":{"type":"string","description":"Event type: \"page_view\", \"custom\", etc."},"id":{"type":"integer","format":"int64","description":"Event ID"},"is_crawler":{"type":"boolean","description":"Whether this event was from a crawler"},"latitude":{"type":["number","null"],"format":"double","description":"Latitude"},"longitude":{"type":["number","null"],"format":"double","description":"Longitude"},"operating_system":{"type":["string","null"],"description":"Operating system"},"page_path":{"type":"string","description":"Page path where the event happened"},"page_title":{"type":["string","null"],"description":"Page title"},"referrer":{"type":["string","null"],"description":"Referrer"},"timestamp":{"type":"string","format":"date-time","description":"When the event occurred"},"visitor_id":{"type":["integer","null"],"format":"int32","description":"Visitor numeric ID"}}},"ActivityGraphQuery":{"type":"object","description":"Query parameters for activity graph endpoint","properties":{"days":{"type":"integer","format":"int32","description":"Number of days to include (default: 365 for last year)"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID to filter activity"},"project_id":{"type":["integer","null"],"format":"int32","description":"Optional project ID to filter activity"}}},"ActivityGraphResponse":{"type":"object","description":"Response for activity graph showing daily deployment activity","required":["days","total_count","start_date","end_date"],"properties":{"days":{"type":"array","items":{"$ref":"#/components/schemas/ActivityDay"},"description":"Array of daily activity counts"},"end_date":{"type":"string","description":"Date range end (YYYY-MM-DD)","example":"2024-12-31"},"start_date":{"type":"string","description":"Date range start (YYYY-MM-DD)","example":"2024-01-01"},"total_count":{"type":"integer","format":"int64","description":"Total count of activities across all days"}}},"AddClusterMemberRequest":{"type":"object","description":"Request body for adding a single member to a running cluster.","required":["role"],"properties":{"node_id":{"type":["integer","null"],"format":"int32","description":"Target worker node ID. Omit or null to run on the control plane."},"role":{"type":"string","description":"Member role. Currently only `replica` is accepted at runtime —\nmonitor is a singleton, primary is elected by pg_auto_failover.","example":"replica"}}},"AddContextRequest":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"AddEnvironmentDomainRequest":{"type":"object","required":["domain","is_primary"],"properties":{"domain":{"type":"string"},"is_primary":{"type":"boolean"}}},"AddEventsRequest":{"type":"object","required":["events"],"properties":{"events":{"type":"string"}}},"AddEventsResponse":{"type":"object","required":["event_count","message"],"properties":{"event_count":{"type":"integer","minimum":0},"message":{"type":"string"}}},"AddManagedDomainApiRequest":{"type":"object","description":"Request to add a managed domain","required":["domain"],"properties":{"auto_manage":{"type":"boolean"},"domain":{"type":"string","example":"example.com"},"generated_hostname_mode":{"type":["string","null"],"description":"Generated hostname layout: `\"standard\"` (default) or `\"flat\"`."},"sync_generated_records":{"type":"boolean","description":"Opt in to reconciling generated hostnames into this domain's DNS zone."}}},"AdminGateResponse":{"type":"object","required":["allowed_ips","allowed_hosts","trust_forwarded_for","source","editable"],"properties":{"allowed_hosts":{"type":"array","items":{"type":"string"},"description":"`Host` header values allowed. Empty = any host."},"allowed_ips":{"type":"array","items":{"type":"string"},"description":"IPs / CIDRs allowed to reach the admin listener. Empty = any source."},"editable":{"type":"boolean","description":"True when the config is writable through this API. False when env\nvars are dictating the active config."},"source":{"$ref":"#/components/schemas/AdminGateSource","description":"Where the active config came from."},"trust_forwarded_for":{"type":"boolean","description":"When true, the gate trusts `X-Forwarded-For` from loopback peers."}}},"AdminGateSource":{"type":"string","description":"Where the active gate configuration came from. Env-supplied configs are\nfrozen at the process level — the UI shows them read-only and refuses to\npersist DB writes. DB-supplied configs are editable at runtime.","enum":["default","db","env"]},"AgentConfigResponse":{"type":"object","description":"Response DTO for a single agent — masks the encrypted API key.","required":["id","project_id","slug","name","source","enabled","trigger_config","ai_provider","api_key_set","max_turns","timeout_seconds","daily_budget_cents","cooldown_minutes","branch_prefix","deliverable","created_at","updated_at"],"properties":{"ai_model":{"type":["string","null"],"description":"Preferred model for the CLI (e.g. \"sonnet\", \"gpt-5-codex\"). `None` means default."},"ai_provider":{"type":"string"},"ai_provider_key_id":{"type":["integer","null"],"format":"int32"},"api_key_set":{"type":"boolean","description":"`true` if an API key is set; `false` otherwise."},"branch_prefix":{"type":"string"},"config_repo_branch":{"type":["string","null"],"description":"Branch of the config repo to use."},"config_repo_url":{"type":["string","null"],"description":"Private config repo containing .claude/ directory (skills, MCP, plugins)."},"cooldown_minutes":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"daily_budget_cents":{"type":"integer","format":"int32"},"deliverable":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"max_turns":{"type":"integer","format":"int32"},"mcp_servers_config":{"description":"MCP servers config (Claude Code settings.json mcpServers format).\nCredential-bearing legacy inline values are write-only and appear as\n`***`. Omit this field on update to preserve their stored values."},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"prompt":{"type":["string","null"]},"sandbox_enabled":{"type":["boolean","null"],"description":"None = use global sandbox setting, true = force on, false = force off"},"skills_config":{"description":"Skills config as JSON array."},"slug":{"type":"string"},"source":{"type":"string"},"timeout_seconds":{"type":"integer","format":"int32"},"tools_config":{"description":"Tools config as JSON array. Legacy custom-tool webhook URLs and headers\nare write-only and appear as `***`. Omit this field on update to\npreserve their stored values."},"trigger_config":{},"updated_at":{"type":"string"},"webhook_token":{"type":["string","null"],"description":"Secret token for the `X-Webhook-Token` header. Shown once when created,\nmasked with `***` prefix in subsequent reads."},"webhook_url":{"type":["string","null"],"description":"Public webhook URL for triggering this agent externally.\nOnly set when `on: { webhook: true }` is configured.\nUsage: `POST {webhook_url}` with header `X-Webhook-Token: {webhook_token}`"}}},"AgentRunLogResponse":{"type":"object","required":["id","run_id","level","message","created_at"],"properties":{"created_at":{"type":"string"},"id":{"type":"integer","format":"int64"},"level":{"type":"string"},"message":{"type":"string"},"metadata":{},"run_id":{"type":"integer","format":"int32"}}},"AgentRunResponse":{"type":"object","required":["id","project_id","source","trigger_type","status","tokens_input","tokens_output","estimated_cost_cents","files_changed","created_at","sandbox_enabled"],"properties":{"agent_name":{"type":["string","null"],"description":"Name of the agent that created this run, if available."},"agent_slug":{"type":["string","null"],"description":"Slug of the agent that created this run, if available."},"ai_model":{"type":["string","null"]},"ai_output":{"type":["string","null"]},"ai_provider":{"type":["string","null"],"description":"AI provider slug that executed this run (e.g. claude_cli, codex_cli, opencode)."},"ai_reasoning":{"type":["string","null"]},"ai_session_id":{"type":["string","null"],"description":"Claude CLI session UUID for resuming conversations via `--resume`."},"analysis":{"type":["string","null"],"description":"Report / analysis text produced by the agent (used for report/notification deliverables)."},"branch_name":{"type":["string","null"]},"commit_sha":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"config_id":{"type":["integer","null"],"format":"int32","description":"Optional. NULL for ephemeral CLI runs (`source = \"cli_ephemeral\"`) and\nhistorical autofixer runs that pre-date the agent_id column."},"created_at":{"type":"string"},"ephemeral_yaml":{"type":["string","null"],"description":"Full WorkflowYamlConfig as YAML text. Populated only when\n`source = \"cli_ephemeral\"`. Used by the web UI to show a \"View YAML\"\nmodal so the user can see exactly what the executor ran."},"error_message":{"type":["string","null"]},"estimated_cost_cents":{"type":"integer","format":"int32"},"files_changed":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"phase":{"type":["string","null"],"description":"Autofixer phase: \"analyzing\", \"analyzed\", \"fixing\", \"fix_ready\", \"no_fix\",\n\"pr_created\", or NULL for non-autofixer runs."},"pr_number":{"type":["integer","null"],"format":"int32"},"pr_url":{"type":["string","null"]},"preview_url":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"prompt_text":{"type":["string","null"],"description":"Final assembled prompt the AI CLI actually saw (trigger context block +\nYAML prompt, with error-group fields interpolated). Captured once per\nrun. `None` for pre-migration rows."},"run_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AutofixRunConfig","description":"Per-run AI options the user chose when starting an autofixer run\n(provider, model, max_turns, branch). NULL for generic agent runs\nand historical rows. Used to prefill the retry dialog."}]},"sandbox_enabled":{"type":"boolean","description":"Legacy field — all runs now execute in a sandbox. Kept for\nbackwards-compatible JSON shape; always `true`."},"source":{"type":"string","description":"`committed` (the run's config lives in `project_agents`) or\n`cli_ephemeral` (the config was uploaded via the CLI for a one-off\ndry run; see `ephemeral_yaml`)."},"started_at":{"type":["string","null"]},"status":{"type":"string"},"tokens_input":{"type":"integer","format":"int32"},"tokens_output":{"type":"integer","format":"int32"},"trigger_source_id":{"type":["integer","null"],"format":"int32"},"trigger_source_type":{"type":["string","null"]},"trigger_type":{"type":"string"},"user_context":{"type":["string","null"],"description":"User-provided context for this run (e.g. webhook payload, manual instructions)."}}},"AgentRunWithLogsResponse":{"type":"object","required":["run","logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunLogResponse"}},"run":{"$ref":"#/components/schemas/AgentRunResponse"}}},"AgentSandboxSettings":{"type":"object","description":"Global agent sandbox settings. Controls whether agent runs are isolated\ninside Docker containers by default. Individual agents can override this.","properties":{"api_key_encrypted":{"type":["string","null"],"description":"DEPRECATED: use `providers[default_provider].credentials_encrypted` instead.","default":null},"auth_type":{"type":"string","description":"DEPRECATED: use `providers[default_provider].auth_type` instead.","default":"subscription"},"cpu_limit":{"type":"number","format":"double","description":"CPU limit in cores for sandbox containers","default":4.0,"example":4.0},"custom_image":{"type":"string","description":"Custom Docker image (only used when runtime is \"custom\").\nMust have git and claude CLI installed.","default":"","example":""},"default_provider":{"type":"string","description":"Default AI provider for agents: \"claude_cli\", \"opencode\", or \"codex_cli\".\nWorkspaces always use this provider — no per-session override.","default":"claude_cli","example":"claude_cli"},"enabled":{"type":"boolean","description":"Sandbox is always enabled — the executor refuses to run any agent\noutside a sandboxed container. Field is retained so existing settings\nrows still deserialize, but it is ignored at runtime.","default":true},"memory_limit_mb":{"type":"integer","format":"int64","description":"Memory limit in MB for sandbox containers","default":8192,"example":8192,"minimum":0},"network_mode":{"type":"string","description":"Network access level: \"full\" (unrestricted), \"restricted\" (Temps network only), \"none\" (no network)","default":"full","example":"full"},"providers":{"type":"object","description":"Per-provider auth + config. Keyed by provider id (e.g. `claude_cli`,\n`codex_cli`, `opencode`). Adding a new provider only requires a new\ncatalog entry on the Rust side — the JSON column stays migration-free.","default":{},"additionalProperties":{"$ref":"#/components/schemas/ProviderConfig"},"propertyNames":{"type":"string"}},"runtime":{"type":"string","description":"Runtime preset: \"node\", \"bun\", \"python\", \"rust\", \"go\", \"full\", or \"custom\"","default":"node","example":"node"},"sandbox_backend":{"type":["string","null"],"description":"Default isolation backend for sandboxes: \"docker\" (default) or\n\"firecracker\" (ADR-029; requires `temps firecracker setup`). Only\nconsulted when the Firecracker backend probes available — otherwise\nDocker is used regardless.","default":null,"example":"docker"}}},"AgentSandboxSettingsMasked":{"type":"object","description":"Agent sandbox settings with masked per-provider credentials.\nEach provider entry reports only whether a credential is saved, not\nthe encrypted blob itself. Non-sensitive fields (auth_type, default_model,\nextra) are passed through so the UI can render provider-specific state.","required":["default_provider","providers","api_key_saved","auth_type","enabled","runtime","custom_image","cpu_limit","memory_limit_mb","network_mode","sandbox_backend"],"properties":{"api_key_saved":{"type":"boolean"},"auth_type":{"type":"string"},"cpu_limit":{"type":"number","format":"double"},"custom_image":{"type":"string"},"default_provider":{"type":"string"},"enabled":{"type":"boolean"},"memory_limit_mb":{"type":"integer","format":"int64","minimum":0},"network_mode":{"type":"string"},"providers":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ProviderConfigMasked"},"propertyNames":{"type":"string"}},"runtime":{"type":"string"},"sandbox_backend":{"type":"string"}}},"AggregatedBucketItem":{"type":"object","required":["timestamp","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"AggregatedBucketsQuery":{"type":"object","description":"Query parameters for aggregated metrics by time bucket","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events, sessions, or visitors"},"bucket_size":{"type":"string","description":"Time bucket size: \"1 hour\", \"1 day\", \"1 week\", etc. (default: \"1 hour\")"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"AggregatedBucketsResponse":{"type":"object","required":["bucket_size","aggregation_level","items","total"],"properties":{"aggregation_level":{"type":"string"},"bucket_size":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AggregatedBucketItem"}},"total":{"type":"integer","format":"int64"}}},"AggregationLevel":{"type":"string","enum":["events","sessions","visitors"]},"AggregationTemporality":{"type":"string","description":"The aggregation temporality of a Sum/Histogram/ExponentialHistogram metric.\n\nMirrors OTel's `AggregationTemporality` proto enum: whether reported values\nare cumulative since the start of the series (Cumulative) or only the delta\nsince the previous report (Delta).","enum":["unspecified","delta","cumulative"]},"AiAgentBreakdownResponse":{"type":"object","description":"Response wrapping the AI agent breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentBreakdownRow"}},"start_time":{"type":"string"}}},"AiAgentBreakdownRow":{"type":"object","description":"One row in the AI-agent analytics breakdown. `agent` is the canonical\ncrawler name (e.g. `GPTBot`, `Claude-User`), `provider` is the vendor used\nfor grouping + logos. The UI mirrors the browsers card and ranks by\n`request_count`.","required":["provider","agent","purpose","request_count","unique_ips"],"properties":{"agent":{"type":"string"},"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"provider":{"type":"string"},"purpose":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"unique_ips":{"type":"integer","format":"int64"}}},"AiAgentDescriptor":{"type":"object","description":"Static descriptor for one entry in the known-AI-agents taxonomy.","required":["provider","agent","purpose"],"properties":{"agent":{"type":"string"},"provider":{"type":"string"},"purpose":{"type":"string"}}},"AiAgentPageRow":{"type":"object","description":"One row in the pages-by-agent breakdown. Returned by\n[`ProxyLogService::get_ai_agent_pages`] for a single named agent.\n`unique_ips` counts distinct client IPs that hit this path via that agent\n(same definition as the per-agent unique-IPs in [`AiAgentBreakdownRow`]).","required":["path","request_count","unique_ips"],"properties":{"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"path":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"unique_ips":{"type":"integer","format":"int64"}}},"AiAgentPagesResponse":{"type":"object","description":"Response wrapping the per-agent pages breakdown rows.","required":["agent","items","start_time","end_time"],"properties":{"agent":{"type":"string","description":"The agent name this breakdown is scoped to."},"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentPageRow"}},"start_time":{"type":"string"}}},"AiAgentTimelineResponse":{"type":"object","description":"Response wrapping the AI agent timeline rows.","required":["items","start_time","end_time","bucket","group_by"],"properties":{"bucket":{"type":"string","description":"Bucket interval used for the buckets (so the UI can label the x-axis).","example":"1 hour"},"end_time":{"type":"string"},"group_by":{"type":"string","description":"Echoes the grouping dimension actually applied.","example":"provider"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentTimelineRow"}},"start_time":{"type":"string"}}},"AiAgentTimelineRow":{"type":"object","description":"One point in the AI-agent timeline: the request count for a single\n(`bucket`, `key`) pair, where `key` is a provider or agent name depending on\nthe requested grouping. The UI pivots these into one stacked series per\n`key` across the shared bucket x-axis.","required":["bucket","key","request_count"],"properties":{"bucket":{"type":"string","description":"Bucket start in RFC3339 format.","example":"2026-05-29T12:00:00Z"},"key":{"type":"string","description":"Provider or agent name this count belongs to.","example":"OpenAI"},"request_count":{"type":"integer","format":"int64"}}},"AiConfigSettings":{"type":"object","description":"Global AI configuration settings. Controls the default config repo\ncontaining `.claude/` directory (skills, MCP servers, plugins) that\ngets overlaid into every agent sandbox.","properties":{"config_repo":{"type":"string","description":"Global config repo URL in \"owner/repo\" format (e.g. \"myorg/claude-config\").\nCloned at agent run time and overlaid into the sandbox's `.claude/` directory.","default":"","example":""},"config_repo_branch":{"type":"string","description":"Branch of the config repo to use.","default":"main","example":"main"}}},"AiPageBreakdownResponse":{"type":"object","description":"Response wrapping the AI page breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiPageBreakdownRow"}},"start_time":{"type":"string"}}},"AiPageBreakdownRow":{"type":"object","description":"One row in the AI-crawled-pages breakdown. `agent_count` is the number of\n*distinct* AI agents that hit this path, so the UI can show both how heavily\nand how broadly a page is being crawled.","required":["path","request_count","agent_count"],"properties":{"agent_count":{"type":"integer","format":"int64"},"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"path":{"type":"string"},"request_count":{"type":"integer","format":"int64"}}},"AiStatusBreakdownResponse":{"type":"object","description":"Response wrapping the AI status breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiStatusBreakdownRow"}},"start_time":{"type":"string"}}},"AiStatusBreakdownRow":{"type":"object","description":"One row in the AI-agent HTTP status breakdown: the request count for a\nstatus class (`2xx`/`3xx`/`4xx`/`5xx`/`other`) across crawler traffic.","required":["status_class","request_count"],"properties":{"request_count":{"type":"integer","format":"int64"},"status_class":{"type":"string","description":"Status class label.","example":"2xx"}}},"AlarmListResponse":{"type":"object","description":"Paginated list of alarms.","required":["items","total","page","page_size"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AlarmResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"AlarmResponse":{"type":"object","description":"Full alarm representation returned by list/summary endpoints.","required":["id","project_id","alarm_type","severity","status","title","fired_at","created_at","updated_at"],"properties":{"acknowledged_at":{"type":["string","null"],"description":"ISO-8601 UTC timestamp when the alarm was acknowledged, if any."},"acknowledged_by":{"type":["integer","null"],"format":"int32","description":"User ID who acknowledged the alarm, if any."},"alarm_type":{"type":"string"},"container_id":{"type":["integer","null"],"format":"int32"},"created_at":{"type":"string","description":"ISO-8601 UTC timestamp when the row was created."},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"fired_at":{"type":"string","description":"ISO-8601 UTC timestamp when the alarm fired."},"id":{"type":"integer","format":"int32"},"message":{"type":["string","null"]},"metadata":{"description":"Arbitrary JSON metadata attached by the alarm source."},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"description":"ISO-8601 UTC timestamp when the alarm was resolved, if any."},"service_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"status":{"type":"string"},"title":{"type":"string"},"updated_at":{"type":"string","description":"ISO-8601 UTC timestamp when the row was last updated."}}},"AlarmSummaryResponse":{"type":"object","description":"Re-export AlarmSummary for the OpenAPI schema.","required":["total_active","firing","acknowledged","critical","warning","by_type"],"properties":{"acknowledged":{"type":"integer","format":"int32","minimum":0},"by_type":{"type":"object","additionalProperties":{"type":"integer","format":"int32","minimum":0},"propertyNames":{"type":"string"}},"critical":{"type":"integer","format":"int32","minimum":0},"firing":{"type":"integer","format":"int32","minimum":0},"total_active":{"type":"integer","format":"int32","minimum":0},"warning":{"type":"integer","format":"int32","minimum":0}}},"AlertRuleResponse":{"type":"object","required":["id","project_id","name","trigger_type","trigger_config","notification_priority","cooldown_minutes","enabled","created_at","updated_at"],"properties":{"cooldown_minutes":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"enabled":{"type":"boolean"},"environment_filter":{"type":["integer","null"],"format":"int32"},"error_level_filter":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"notification_priority":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"trigger_config":{},"trigger_type":{"type":"string"},"updated_at":{"type":"string"}}},"AllocEntry":{"type":"object","description":"Wire-format allocation. `null` in the JSON when the node hasn't been\nallocated yet — workers should treat that as \"single-host mode, do\nnot bring up the overlay\".","required":["node_id","compute_cidr","bridge_address","underlay_address"],"properties":{"bridge_address":{"type":"string"},"compute_cidr":{"type":"string"},"node_id":{"type":"string","description":"Stable v5 UUID derived from the database node id."},"underlay_address":{"type":"string"}}},"AnalyticsSessionEventsResponse":{"type":"object","required":["session_id","events","total_events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEvent"}},"session_id":{"type":"string"},"total_events":{"type":"integer","minimum":0}}},"AnnotatedSpan":{"type":"object","description":"A single span annotated with the project that originally stored it.\nUsed in `UnifiedTrace` to let the UI colour-code spans by project.","required":["project_id","project_name","span"],"properties":{"project_id":{"type":"integer","format":"int32","description":"The project that stored this span (same as `span.project_id`)."},"project_name":{"type":"string","description":"Human-readable project name for waterfall colour-coding and legend."},"span":{"$ref":"#/components/schemas/SpanRecord","description":"Original span data verbatim from storage."}}},"AnomalyAlgorithm":{"type":"string","description":"Anomaly baseline algorithm. Adding one (e.g. a new robust variant) is a\ncode-only enum addition — no migration, since it lives inside the blob.","enum":["robust","basic","agile","ewma"]},"AnomalyParams":{"type":"object","description":"Seasonal anomaly-band detector parameters (stub — not yet evaluated).","properties":{"algorithm":{"$ref":"#/components/schemas/AnomalyAlgorithm","description":"Baseline model. `robust` is the default (seasonal, stable, flags level\nshifts); `ewma`/`agile` adopt level shifts; `basic` is non-seasonal."},"baseline_lookback_days":{"type":["integer","null"],"format":"int32","description":"How far back to build the baseline. `None` = an evaluator default."},"deviations":{"type":"number","format":"double","description":"Band width in robust standard deviations (Datadog's `bounds`)."},"direction":{"$ref":"#/components/schemas/Direction","description":"Which side(s) of the band a deviation must be on to count."},"pct_anomalous":{"type":"number","format":"double","description":"Fraction (0..=1) of points in the window that must be anomalous to fire."},"seasonality":{"$ref":"#/components/schemas/Seasonality","description":"Seasonality model for the baseline."}}},"AnomalyPreviewPointResponse":{"type":"object","required":["bucket","value","lower","upper","breaching"],"properties":{"breaching":{"type":"boolean"},"bucket":{"type":"string","example":"2025-10-12T12:15:47Z"},"lower":{"type":"number","format":"double","description":"Lower edge of the expected band at this point."},"upper":{"type":"number","format":"double","description":"Upper edge of the expected band at this point."},"value":{"type":"number","format":"double"}}},"AnomalyPreviewRequest":{"type":"object","required":["project_id","metric_name","aggregation","window_secs","detection_config"],"properties":{"aggregation":{"type":"string","description":"One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"Must be an `anomaly` detector — the band to backtest."},"end_time":{"type":["string","null"],"description":"RFC 3339; defaults to now.","example":"2025-10-12T12:15:47Z"},"metric_name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":["string","null"],"description":"RFC 3339; defaults to 7 days before `end_time`.","example":"2025-10-12T12:15:47Z"},"window_secs":{"type":"integer","format":"int32"}}},"AnomalyPreviewResponse":{"type":"object","required":["points","breach_count","baseline_samples","sufficient"],"properties":{"baseline_samples":{"type":"integer","format":"int64","description":"Baseline sample count (drives the `sufficient` flag)."},"breach_count":{"type":"integer","format":"int64","description":"How many points in the range would have fired."},"points":{"type":"array","items":{"$ref":"#/components/schemas/AnomalyPreviewPointResponse"}},"sufficient":{"type":"boolean","description":"Whether the baseline had enough history for a trustworthy band."}}},"ApiKeyListResponse":{"type":"object","required":["api_keys","total"],"properties":{"api_keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"ApiKeyResponse":{"type":"object","required":["id","name","key_prefix","role_type","is_active","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"key_prefix":{"type":"string"},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"role_type":{"type":"string"}}},"AppSettings":{"type":"object","description":"Application settings stored in the database\nAll fields have sensible defaults for easy onboarding","properties":{"agent_sandbox":{"oneOf":[{"$ref":"#/components/schemas/AgentSandboxSettings"}],"default":{"default_provider":"claude_cli","providers":{},"auth_type":"subscription","api_key_encrypted":null,"enabled":true,"runtime":"node","custom_image":"","cpu_limit":4.0,"memory_limit_mb":8192,"network_mode":"full","sandbox_backend":null}},"ai_config":{"oneOf":[{"$ref":"#/components/schemas/AiConfigSettings"}],"default":{"config_repo":"","config_repo_branch":"main"}},"build_limits":{"oneOf":[{"$ref":"#/components/schemas/BuildLimitsSettings","description":"Build-time resource limits applied on the control plane to prevent\n`docker build` from saturating host CPU/RAM. Worker nodes are\nintentionally NOT subject to these limits (each worker is dedicated\nhardware that already has its own per-host headroom)."}],"default":{"max_concurrent":2,"cpu_limit_cores":0.0,"memory_limit_mb":0}},"cluster_dns":{"oneOf":[{"$ref":"#/components/schemas/ClusterDnsSettings","description":"Cluster-DNS resolver settings (ADR-024, experimental beta). Off by\ndefault — see `ClusterDnsSettings` for the incident background and\ntrade-offs. Must be explicitly enabled by operators who need\n`*.temps.local` service-to-service resolution inside containers."}],"default":{"enabled":false}},"console_version":{"type":["string","null"],"description":"Binary version tag (e.g. \"v0.1.0\") of the *console* process\n(`temps serve`, role=all or role=console) that last started. Written\non console startup; read by the standalone `temps proxy` to detect\nversion skew during a rolling upgrade (ADR-017 Phase 3). `None` on\ninstalls that never ran a console build carrying this field.\n\nThis is informational state written by the binary itself — NOT an\noperator-tunable setting. It is intentionally absent from\n`AppSettingsResponse` and the PATCH path so an operator cannot\naccidentally overwrite the self-recorded value.","default":null},"container_logs":{"oneOf":[{"$ref":"#/components/schemas/ContainerLogSettings"}],"default":{"max_size":"50m","max_file":3,"service_max_size":"20m","service_max_file":3}},"disk_space_alert":{"oneOf":[{"$ref":"#/components/schemas/DiskSpaceAlertSettings"}],"default":{"enabled":true,"threshold_percent":80,"check_interval_seconds":300,"monitor_path":null}},"dns_provider":{"oneOf":[{"$ref":"#/components/schemas/DnsProviderSettings"}],"default":{"provider":"manual","cloudflare_api_key":null}},"docker_registry":{"oneOf":[{"$ref":"#/components/schemas/DockerRegistrySettings"}],"default":{"enabled":false,"registry_url":null,"username":null,"password":null,"tls_verify":true,"ca_certificate":null}},"edge_target":{"type":["string","null"],"description":"Public edge target that generated DNS records point at when a managed\ndomain opts into automatic record sync. An IPv4/IPv6 address produces an\n`A`/`AAAA` record; anything else is treated as a `CNAME` target. `None`\ndisables DNS record sync regardless of per-domain opt-in.","default":null},"external_url":{"type":["string","null"],"default":null},"insecure_tls":{"type":"boolean","description":"Skip TLS certificate verification on outbound HTTP clients built by the\nserver (deployer, agent, remote service client). Strictly opt-in for\noperators running self-signed control plane / worker certs on a trusted\ninternal network. Worker→control-plane traffic that traverses the public\ninternet must keep this `false` — otherwise a MitM steals the join token.","default":false},"internal_url":{"type":["string","null"],"description":"URL that service containers use to reach the Temps API from *inside*\nthe Docker network (OTLP metrics ingest, agent callbacks, etc.). On\nDocker Desktop this defaults to `http://host.docker.internal:`;\non Linux it requires the `host.docker.internal:host-gateway` host\nmapping (which Temps adds to provisioned containers). Distinct from\n`external_url`, which is the public-facing address.","default":null},"letsencrypt":{"oneOf":[{"$ref":"#/components/schemas/LetsEncryptSettings"}],"default":{"email":null,"environment":"production"}},"monitoring":{"oneOf":[{"$ref":"#/components/schemas/MonitoringSettings","description":"Metrics observability settings. Controls the MetricsStore backend,\nscrape interval, and tiered retention windows."}],"default":{"enabled":false,"store":"timescale_db","scrape_interval_secs":30,"retention_raw_days":7,"retention_hourly_days":90,"retention_daily_years":2,"clickhouse_url":null}},"multi_node":{"oneOf":[{"$ref":"#/components/schemas/MultiNodeSettings"}],"default":{"join_token_hash":null,"private_address":null,"legacy_shared_token_enabled":true,"cluster_ca_cert_pem":null,"cluster_ca_key_encrypted":null,"require_mtls":false,"node_cpu_alert_percent":90.0,"node_memory_alert_percent":90.0,"node_disk_alert_percent":90.0}},"observability_compression":{"oneOf":[{"$ref":"#/components/schemas/ObservabilityCompressionSettings","description":"TimescaleDB compression delays for immutable observability data.\nChanges are applied at runtime by the Settings API."}],"default":{"proxy_logs_after_hours":24,"otel_spans_after_hours":24}},"observability_retention":{"oneOf":[{"$ref":"#/components/schemas/ObservabilityRetentionSettings","description":"Retention windows for raw proxy and OpenTelemetry telemetry.\nTimescaleDB policies are updated at runtime by the Settings API."}],"default":{"proxy_logs_days":30,"otel_spans_days":90,"otel_logs_days":90,"otel_metrics_days":90}},"on_demand_tls":{"oneOf":[{"$ref":"#/components/schemas/OnDemandTlsSettings"}],"default":{"enabled":false,"zone":null,"max_concurrent":3,"hourly_cap":10,"deployment_url_mode":"http"}},"preview_domain":{"type":"string","default":"localho.st"},"preview_gateway":{"oneOf":[{"$ref":"#/components/schemas/PreviewGatewaySettings"}],"default":{"image":"ghcr.io/gotempsh/temps-preview-gateway:latest","host_port":8090,"auto_upgrade":true}},"rate_limiting":{"oneOf":[{"$ref":"#/components/schemas/RateLimitSettings"}],"default":{"enabled":false,"max_requests_per_minute":60,"max_requests_per_hour":1000,"whitelist_ips":[],"blacklist_ips":[]}},"require_mfa_for_admins":{"type":"boolean","description":"When `true`, any user holding the `Admin` role must have MFA enrolled\n(`users.mfa_enabled = true`) to complete a **password** login. Users\nwithout MFA enrolled are rejected with a typed error instructing them\nto enroll before retrying. This only gates the password-login path\n(`AuthService::login`) -- SSO/OIDC logins are handled by a separate\ncode path (`OidcService::resolve_user` + `oidc_handler`) and are\nintentionally unaffected, since federating identity to a\nproperly-hardened IdP is itself an acceptable alternative to local\nTOTP MFA. Modeled as a settings row (not an env var) per CLAUDE.md so\nan operator can flip it at runtime via the Settings API without\nrestarting the binary.","default":false},"screenshots":{"oneOf":[{"$ref":"#/components/schemas/ScreenshotSettings"}],"default":{"enabled":false,"provider":"local","url":""}},"security_headers":{"oneOf":[{"$ref":"#/components/schemas/SecurityHeadersSettings"}],"default":{"enabled":false,"preset":"moderate","content_security_policy":"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'","x_frame_options":"SAMEORIGIN","x_content_type_options":"nosniff","x_xss_protection":"1; mode=block","strict_transport_security":"max-age=31536000; includeSubDomains","referrer_policy":"strict-origin-when-cross-origin","permissions_policy":"geolocation=(), microphone=(), camera=()"}},"setup_complete":{"type":"boolean","description":"Set to `true` by `temps setup` (all modes) once initial configuration\nhas been applied. The web onboarding wizard reads this from the server\nand skips itself when true, preventing the \"Configure Base Domain\" wall\nfrom appearing on installs that were already configured via the CLI.","default":false}}},"AppSettingsResponse":{"type":"object","description":"Safe response for application settings that masks sensitive fields","required":["preview_domain","screenshots","letsencrypt","dns_provider","security_headers","rate_limiting","docker_registry","disk_space_alert","container_logs","agent_sandbox","ai_config","preview_gateway","multi_node","monitoring","observability_compression","observability_retention","effective_metrics_store","effective_observability_store","insecure_tls","setup_complete","require_mfa_for_admins","cluster_dns","build_limits"],"properties":{"agent_sandbox":{"$ref":"#/components/schemas/AgentSandboxSettingsMasked"},"ai_config":{"$ref":"#/components/schemas/AiConfigSettings"},"build_limits":{"$ref":"#/components/schemas/BuildLimitsSettings","description":"Build-time resource limits (control-plane only). No sensitive content,\npassed through as-is."},"cluster_dns":{"$ref":"#/components/schemas/ClusterDnsSettings","description":"Cluster-DNS resolver settings (ADR-024, experimental beta). No masking\nneeded — `enabled` is a plain bool with no sensitive content. Passed\nthrough as-is so the settings UI can read and toggle the flag."},"container_logs":{"$ref":"#/components/schemas/ContainerLogSettings"},"disk_space_alert":{"$ref":"#/components/schemas/DiskSpaceAlertSettings"},"dns_provider":{"$ref":"#/components/schemas/DnsProviderSettingsMasked"},"docker_registry":{"$ref":"#/components/schemas/DockerRegistrySettingsMasked"},"edge_target":{"type":["string","null"],"description":"Public edge target that synced DNS records point at (IP → A/AAAA, else CNAME)."},"effective_metrics_store":{"$ref":"#/components/schemas/MetricsStoreKind","description":"The storage backend the runtime is **actually** using for metrics,\nafter reconciling the `monitoring.store` toggle with the server's\n`TEMPS_CLICKHOUSE_*` configuration. When `monitoring.store` is\n`click_house` but those env vars are not fully set, the runtime falls\nback to TimescaleDB — in that case this reports `timescale_db` even\nthough `monitoring.store` says `click_house`. The UI shows this as the\neffective backend and warns when it diverges from the configured store."},"effective_observability_store":{"$ref":"#/components/schemas/MetricsStoreKind","description":"Storage backend actually used for proxy logs, OTel spans, and OTel\nmetrics. OTel logs remain TimescaleDB-backed. Unlike resource metrics,\nthese domains switch to ClickHouse whenever the server-level ClickHouse\nconnection is configured; they do not use the monitoring store toggle."},"external_url":{"type":["string","null"]},"insecure_tls":{"type":"boolean"},"internal_url":{"type":["string","null"]},"letsencrypt":{"$ref":"#/components/schemas/LetsEncryptSettings"},"monitored_services_count":{"type":["integer","null"],"format":"int64","description":"Number of enabled, running services the MetricsScraper currently\nincludes. Used for the lightweight storage estimate in the UI.","minimum":0},"monitoring":{"$ref":"#/components/schemas/MonitoringSettingsMasked"},"multi_node":{"$ref":"#/components/schemas/MultiNodeSettingsMasked"},"observability_compression":{"$ref":"#/components/schemas/ObservabilityCompressionSettings","description":"TimescaleDB compression delays for immutable proxy logs and OTel spans."},"observability_retention":{"$ref":"#/components/schemas/ObservabilityRetentionSettings","description":"Retention windows for raw proxy logs and OpenTelemetry data."},"preview_domain":{"type":"string"},"preview_gateway":{"$ref":"#/components/schemas/PreviewGatewaySettingsMasked"},"rate_limiting":{"$ref":"#/components/schemas/RateLimitSettings"},"require_mfa_for_admins":{"type":"boolean","description":"When enabled, Admin-role accounts without MFA enrolled are rejected\nat password login (bherila/temps#32). SSO/OIDC logins are unaffected."},"screenshots":{"$ref":"#/components/schemas/ScreenshotSettings"},"security_headers":{"$ref":"#/components/schemas/SecurityHeadersSettings"},"setup_complete":{"type":"boolean","description":"Whether `temps setup` has been run at least once. The web onboarding\nwizard checks this field on load and skips itself when true."}}},"ApplyHostnameModeRequest":{"type":"object","description":"Request to apply a hostname mode (recompute + optional DNS sync).","required":["mode"],"properties":{"mode":{"type":"string","description":"Target mode to apply: `\"standard\"` or `\"flat\"`."},"sync_dns":{"type":"boolean","description":"Also reconcile the provider's DNS zone for the affected hostnames."}}},"ArchiveMode":{"type":"string","enum":["off","on","always","unknown"]},"AssignRoleRequest":{"type":"object","required":["user_id","role_type"],"properties":{"role_type":{"type":"string"},"user_id":{"type":"integer","format":"int32"}}},"AttachScheduleServicesRequest":{"type":"object","description":"Body for `POST /api/backups/schedules/{id}/services` — attach external\nservices to a backup schedule. Idempotent.","required":["service_ids"],"properties":{"service_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"External service ids to attach. Duplicates are de-duplicated server-side."}}},"AttachScheduleServicesResponse":{"type":"object","description":"Response for `POST /api/backups/schedules/{id}/services`.","required":["inserted","total_attached"],"properties":{"inserted":{"type":"integer","format":"int64","description":"Number of rows actually inserted (excludes rows skipped by\n`ON CONFLICT DO NOTHING`).","minimum":0},"total_attached":{"type":"integer","description":"Total number of services now attached to the schedule.","minimum":0}}},"AuditLogIpInfo":{"type":"object","description":"IP address information in audit log","required":["ip"],"properties":{"city":{"type":["string","null"],"description":"City name","example":"San Francisco"},"country":{"type":["string","null"],"description":"Country code","example":"US"},"ip":{"type":"string","description":"IP address","example":"192.168.1.1"},"latitude":{"type":["number","null"],"format":"double","description":"Latitude","example":37.7749},"longitude":{"type":["number","null"],"format":"double","description":"Longitude","example":122.4194}}},"AuditLogResponse":{"type":"object","description":"Response type for audit log entries","required":["id","operation_type","audit_date"],"properties":{"audit_date":{"type":"integer","format":"int64","description":"When the action occurred","example":11932193},"data":{"description":"Additional context about the action"},"id":{"type":"integer","format":"int32","description":"Unique identifier for the audit log entry"},"ip_address":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AuditLogIpInfo","description":"IP address details"}]},"operation_type":{"type":"string","description":"The type of action that was performed","example":"USER_LOGIN"},"user":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AuditLogUserInfo","description":"User details who performed the action"}]},"user_id":{"type":["integer","null"],"format":"int32","description":"The user who performed the action (`null` when that account has\nsince been deleted; `data` retains the original actor context)"}}},"AuditLogUserInfo":{"type":"object","description":"User information in audit log","required":["id","name","email"],"properties":{"email":{"type":"string","description":"User's email","example":"john.doe@example.com"},"id":{"type":"integer","format":"int32","description":"User ID"},"name":{"type":"string","description":"User's name","example":"John Doe"}}},"AuthFlavorDto":{"type":"object","description":"One auth flavor surfaced to the UI. Mirrors `AuthFlavor` in the catalog\nbut without the seed-path / env-var fields the frontend doesn't need\n(those are server-side only — exposing them just bloats the response).","required":["id","label","description","format"],"properties":{"description":{"type":"string"},"env_var":{"type":["string","null"],"description":"For `api_key` format: the env var name that will be set inside the\nsandbox. Useful for showing the user \"we'll set OPENAI_API_KEY\" so\nthey know what their key controls."},"format":{"type":"string","description":"`api_key`, `oauth_token`, or `config_file` — drives which input UI\nthe settings page renders (single-line vs. multi-line textarea)."},"id":{"type":"string"},"label":{"type":"string"}}},"AuthResponse":{"type":"object","required":["success","message","mfa_required"],"properties":{"message":{"type":"string"},"mfa_required":{"type":"boolean"},"success":{"type":"boolean"},"user_id":{"type":["integer","null"],"format":"int32"}}},"AuthStatusResponse":{"type":"object","required":["status"],"properties":{"cli_token":{"type":["string","null"]},"status":{"type":"string"}}},"AuthTokenResponse":{"type":"object","required":["access_token","refresh_token","expires_at"],"properties":{"access_token":{"type":"string"},"expires_at":{"type":"integer","format":"int64"},"refresh_token":{"type":"string"}}},"AutoWatchParams":{"type":"object","description":"Auto-watch (Watchdog-style) detector parameters (stub — not evaluated).","properties":{"direction":{"$ref":"#/components/schemas/Direction","description":"The engine self-tunes the band; the user supplies only the direction."}}},"AutofixRunConfig":{"type":"object","description":"User-chosen per-run options, persisted as JSON in `agent_runs.run_config`.\nEvery field is optional — unset fields fall back to the provider defaults\nin settings, then to built-in defaults.","properties":{"branch":{"type":["string","null"],"description":"Branch to clone instead of the project's main branch.","default":null},"max_turns":{"type":["integer","null"],"format":"int32","description":"Per-run turn cap applied to every phase of this run. Only enforced\nfor CLIs with a turn flag (Claude Code); Codex/OpenCode run to\ncompletion. `None` uses the provider's per-phase defaults.","default":null},"model":{"type":["string","null"],"description":"Model id for the chosen provider. `None` uses the provider's saved\ndefault model, or the CLI's own default.","default":null},"provider":{"type":["string","null"],"description":"AI provider id (\"claude_cli\", \"codex_cli\", \"opencode\"). `None` uses\nthe platform default provider from agent sandbox settings.","default":null}}},"AutofixerRunResponse":{"type":"object","required":["id","project_id","status","tokens_input","tokens_output","files_changed","created_at"],"properties":{"ai_model":{"type":["string","null"]},"ai_output":{"type":["string","null"]},"ai_provider":{"type":["string","null"],"description":"AI provider slug this run executes with (e.g. claude_cli, codex_cli)."},"analysis":{"type":["string","null"]},"branch_name":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"files_changed":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"phase":{"type":["string","null"]},"pr_number":{"type":["integer","null"],"format":"int32"},"pr_url":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"run_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AutofixRunConfig","description":"Per-run options the run was started with; used to prefill the\nretry / start-over dialog."}]},"started_at":{"type":["string","null"]},"status":{"type":"string"},"tokens_input":{"type":"integer","format":"int32"},"tokens_output":{"type":"integer","format":"int32"},"trigger_source_id":{"type":["integer","null"],"format":"int32"},"user_context":{"type":["string","null"]}}},"AutofixerRunWithLogsResponse":{"type":"object","required":["run","logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunLogResponse"}},"run":{"$ref":"#/components/schemas/AutofixerRunResponse"}}},"AvailableContainerInfo":{"type":"object","description":"Available Docker container that can be imported as a service","required":["container_id","container_name","image","version","service_type","is_running"],"properties":{"container_id":{"type":"string","description":"Container ID or name","example":"abc123def456"},"container_name":{"type":"string","description":"Container display name","example":"my-postgres"},"exposed_ports":{"type":"array","items":{"type":"integer","format":"int32","minimum":0},"description":"Exposed ports (e.g., [5432] for PostgreSQL, [6379] for Redis)"},"image":{"type":"string","description":"Docker image name (e.g., \"gotempsh/postgres-walg:18-bookworm\")","example":"gotempsh/postgres-walg:18-bookworm"},"is_running":{"type":"boolean","description":"Whether the container is currently running","example":true},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute","description":"Service type this container represents"},"version":{"type":"string","description":"Extracted version from image","example":"18"}}},"AvailablePermissions":{"type":"object","description":"Response containing all available permissions for frontend validation","required":["permissions","roles"],"properties":{"permissions":{"type":"array","items":{"$ref":"#/components/schemas/PermissionInfo"},"description":"All available permissions in the system"},"roles":{"type":"array","items":{"$ref":"#/components/schemas/RoleInfo"},"description":"All available roles"}}},"BackupAlertListResponse":{"type":"object","description":"Response body for the list-backup-alerts endpoint.","required":["alerts"],"properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/BackupAlertResponse"},"description":"All currently open (unresolved) alerts, newest first."}}},"BackupAlertResponse":{"type":"object","description":"A single open backup alert surfaced in the UI banner.\n\nAlerts are auto-opened by the watcher and auto-resolved when the triggering\ncondition clears. No manual dismiss is required or supported.\n\nThe optional `schedule_s3_source_id` field is included so the UI can\ndeep-link an `overdue_schedule` alert to the S3 source detail page that\nhosts the schedule. `stalled_job` alerts no longer carry a deep-link\ntarget — the alert message text contains the backup id for display.","required":["id","kind","severity","message","opened_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Database id of the alert row."},"kind":{"type":"string","description":"`\"overdue_schedule\"` or `\"stalled_job\"`."},"message":{"type":"string","description":"Human-readable description of the alert condition."},"opened_at":{"type":"string","description":"RFC 3339 timestamp when the alert was opened.","example":"2026-05-15T10:00:00Z"},"schedule_id":{"type":["integer","null"],"format":"int32","description":"FK to `backup_schedules.id`. Set for `overdue_schedule` alerts."},"schedule_name":{"type":["string","null"],"description":"Human-readable name of the linked schedule, if applicable."},"schedule_s3_source_id":{"type":["integer","null"],"format":"int32","description":"FK to `backup_schedules.s3_source_id`. The UI uses this to deep-link\nthe alert to the S3 source detail page that hosts the schedule.\nSet for `overdue_schedule` alerts."},"severity":{"type":"string","description":"`\"warning\"` or `\"critical\"`."}}},"BackupResponse":{"type":"object","description":"Response type for backup","required":["id","name","backup_id","backup_type","state","started_at","s3_source_id","s3_location","metadata","compression_type","created_by","tags"],"properties":{"attempts":{"type":["integer","null"],"format":"int32","description":"How many times this job has been claimed and run. `null` for legacy\nbackups with no `backup_jobs` row."},"backup_id":{"type":"string"},"backup_type":{"type":"string"},"checksum":{"type":["string","null"]},"completed_at":{"type":["integer","null"],"format":"int64"},"compression_type":{"type":"string"},"created_by":{"type":"integer","format":"int32"},"current_step":{"type":["string","null"],"description":"Name of the engine step currently executing (e.g., `\"walg_push\"`).\n`null` when no `backup_jobs` row exists for this backup (legacy rows\npre-dating ADR-014), or when the job has not yet completed its first step."},"error_message":{"type":["string","null"]},"expires_at":{"type":["integer","null"],"format":"int64"},"external_service":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ExternalServiceSummary","description":"External service that owns this backup (Redis, Postgres, etc.).\n`null` for control-plane backups (the Temps server's own database)."}]},"file_count":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"live_size_bytes":{"type":["integer","null"],"format":"int64","description":"Best-effort partial size while a backup is still running, computed\nby listing the S3 prefix. Null when the backup is finished\n(`size_bytes` is authoritative in that case)."},"max_attempts":{"type":["integer","null"],"format":"int32","description":"Maximum attempts before the job is permanently failed. `null` for\nlegacy backups."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Resolved wall-clock timeout for this backup job (seconds). `null` for\nlegacy backups. Derived from the three-tier resolution order:\ncaller override → schedule override → engine default."},"metadata":{},"name":{"type":"string"},"s3_location":{"type":"string"},"s3_source_id":{"type":"integer","format":"int32"},"schedule_id":{"type":["integer","null"],"format":"int32"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Final size of the backup once completed. Null while running."},"started_at":{"type":"integer","format":"int64"},"state":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}}},"BackupScheduleResponse":{"type":"object","description":"Response type for backup schedule","required":["id","name","backup_type","retention_period","s3_source_id","schedule_expression","enabled","created_at","updated_at","tags","target_all_services","include_control_plane"],"properties":{"backup_type":{"type":"string"},"created_at":{"type":"integer","format":"int64"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"include_control_plane":{"type":"boolean","description":"When `true`, every run also produces a `control_plane` backup\n(Temps's own Postgres). When `false`, only the external service\nfan-out happens."},"last_run":{"type":["integer","null"],"format":"int64"},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Per-schedule wall-clock timeout override for backup jobs (seconds).\n`null` means the engine-family default is used. See\n`temps_backup_core::timeouts::default_max_runtime_secs`."},"name":{"type":"string"},"next_run":{"type":["integer","null"],"format":"int64"},"retention_period":{"type":"integer","format":"int32"},"s3_source_id":{"type":"integer","format":"int32"},"schedule_expression":{"type":"string","example":"0 0 * * *"},"tags":{"type":"array","items":{"type":"string"}},"target_all_services":{"type":"boolean","description":"When `true`, the schedule auto-includes every external service on\nthe host (and any future ones). When `false`, the schedule only\ntargets services attached via `backup_schedule_services`."},"updated_at":{"type":"integer","format":"int64"}}},"BitbucketAuthInput":{"oneOf":[{"type":"object","description":"Personal / Workspace / Repository Access Token.","required":["token","type"],"properties":{"token":{"type":"string","description":"The Bitbucket access token value."},"type":{"type":"string","enum":["access_token"]}}},{"type":"object","description":"HTTP Basic / App Password authentication.","required":["username","password","type"],"properties":{"password":{"type":"string","description":"App password generated in Bitbucket security settings."},"type":{"type":"string","enum":["app_password"]},"username":{"type":"string","description":"Bitbucket account username."}}}],"description":"Authentication input for a Bitbucket Cloud provider. Use `access_token` for\na Repository or Workspace Access Token (PAT), or `username` + `app_password`\nfor App Password (HTTP Basic) authentication."},"BlobResponse":{"type":"object","description":"Response after uploading a blob","required":["url","pathname","contentType","size","uploadedAt"],"properties":{"contentType":{"type":"string","description":"Content type of the blob","example":"image/png"},"pathname":{"type":"string","description":"Original pathname","example":"images/avatar-abc123.png"},"size":{"type":"integer","format":"int64","description":"Size in bytes","example":12345},"uploadedAt":{"type":"string","format":"date-time","description":"Upload timestamp","example":"2025-01-03T12:00:00Z"},"url":{"type":"string","description":"URL path to access the blob","example":"/api/blob/123/images/avatar-abc123.png"}}},"BlobStatusResponse":{"type":"object","description":"Response for Blob service status","required":["enabled","healthy"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image being used","example":"ghcr.io/rustfs/rustfs:0.5.0"},"enabled":{"type":"boolean","description":"Whether the Blob service is enabled","example":true},"healthy":{"type":"boolean","description":"Whether the service is healthy","example":true},"version":{"type":["string","null"],"description":"Current version (if running)","example":"0.5.0"}}},"BranchInfo":{"type":"object","required":["name","commit_sha","protected"],"properties":{"commit_sha":{"type":"string"},"name":{"type":"string"},"protected":{"type":"boolean"}}},"BranchListResponse":{"type":"object","required":["branches"],"properties":{"branches":{"type":"array","items":{"$ref":"#/components/schemas/BranchInfo"}}}},"BrowserCount":{"type":"object","required":["browser","count","percentage"],"properties":{"browser":{"type":"string"},"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"}}},"BrowsersQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"BuildConfiguration":{"type":"object","description":"Build configuration (for building images from source)","required":["context","args"],"properties":{"args":{"type":"object","description":"Build arguments","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"context":{"type":"string","description":"Build context (Dockerfile path or buildpack)"},"dockerfile":{"type":["string","null"],"description":"Dockerfile path (relative to context)"},"target":{"type":["string","null"],"description":"Target stage (for multi-stage builds)"}}},"BuildLimitsSettings":{"type":"object","description":"Control-plane build resource limits.\n\nCaps how many builds run concurrently AND how much CPU/memory each build\nis allowed to consume. A single global semaphore in the deployer crate\ngates every `DockerRuntime::build_image` call to `max_concurrent`. When\nthe semaphore is full, additional builds queue and wait — they do not\nfail. Per-build CPU/memory caps are forwarded to Docker via\n`BuildImageOptions { memory, cpuquota, cpuperiod }`.\n\n`cpu_limit_cores = 0.0` or `memory_limit_mb = 0` means \"no explicit cap\"\n— fall back to the legacy 50%-of-host heuristic for backwards\ncompatibility with operators who never visit the settings page.","properties":{"cpu_limit_cores":{"type":"number","format":"float","description":"CPU cores allowed per build (float, e.g. 2.0 = 2 cores, 0.5 = half\na core). 0 means \"use the legacy 50%-of-host default\".","default":0.0,"example":2.0,"minimum":0},"max_concurrent":{"type":"integer","format":"int32","description":"Maximum number of `docker build` operations allowed to run at the\nsame time on the control plane. Additional builds queue. Min 1.","default":2,"example":2,"minimum":1},"memory_limit_mb":{"type":"integer","format":"int32","description":"Memory allowed per build, in megabytes. 0 means \"use the legacy\n50%-of-host default\". Docker enforces this as a hard cap — builds\nthat exceed it OOM-kill.","default":0,"example":2048,"minimum":0}}},"CancelBackupResponse":{"type":"object","description":"Response body for cancel endpoints.","required":["cancelled"],"properties":{"cancelled":{"type":"integer","format":"int64","description":"Number of rows that were actually flipped to `failed`. `0` is a valid\nsuccess and means the backup was already terminal — the call is\nidempotent.","minimum":0}}},"CertStatusResponse":{"type":"object","description":"Current on-demand cert status for a single hostname (ADR-018 §5). Backs\n`GET /domains/by-host/{hostname}/cert-status`.","required":["hostname"],"properties":{"backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand negative-cache deadline (epoch millis), when in backoff."},"hostname":{"type":"string","description":"SNI hostname."},"last_attempt":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/OnDemandCertAttemptResponse","description":"The most recent on-demand issuance attempt for this hostname, if any."}]},"status":{"type":["string","null"],"description":"Current cert lifecycle status from the `domains` row, when one exists."}}},"ChallengeConfig":{"type":"object","description":"Challenge configuration (future feature)\nFor CAPTCHA, JS challenges, proof-of-work, etc.","required":["challengeType","difficulty"],"properties":{"challengeType":{"type":"string","description":"Challenge type: \"captcha\", \"js_challenge\", \"proof_of_work\""},"difficulty":{"type":"integer","format":"int32","description":"Challenge difficulty level (1-10)","minimum":0},"protectedPaths":{"type":"array","items":{"type":"string"},"description":"Paths that require challenges"}}},"ChallengeError":{"type":"object","required":["type","detail","status"],"properties":{"detail":{"type":"string","description":"Human-readable error description"},"status":{"type":"integer","format":"int32","description":"HTTP status code"},"type":{"type":"string","description":"Error type (e.g., \"urn:ietf:params:acme:error:unauthorized\")"}}},"ChallengeValidationStatus":{"type":"object","required":["type","url","status","token"],"properties":{"error":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeError","description":"Error details if validation failed"}]},"status":{"type":"string","description":"Challenge status (e.g., \"pending\", \"valid\", \"invalid\")"},"token":{"type":"string","description":"Challenge token"},"type":{"type":"string","description":"Challenge type (e.g., \"dns-01\", \"http-01\")"},"url":{"type":"string","description":"Challenge validation URL"},"validated":{"type":["string","null"],"description":"When the challenge was validated (if successful)"}}},"ChangePasswordRequest":{"type":"object","required":["current_password","new_password"],"properties":{"current_password":{"type":"string","example":"current_password_value"},"mfa_code":{"type":["string","null"],"description":"TOTP code (or recovery code). Required iff the user has MFA enabled.","example":"123456"},"new_password":{"type":"string","example":"new_password_value"},"revoke_other_sessions":{"type":"boolean","description":"When true, every session OTHER than the one making this request is\nrevoked. Defaults to false; the UI surfaces this as a checkbox."}}},"ChangeProjectSourceRequest":{"type":"object","description":"Change a project's source type to a Git-less type (docker_image /\nstatic_files / manual). Switching TO `git` is done via the Git settings\nendpoint (which also supplies the repository + provider connection).","required":["source_type"],"properties":{"source_type":{"$ref":"#/components/schemas/SourceType"}}},"ChatCompletionChoice":{"type":"object","required":["index","message"],"properties":{"finish_reason":{"type":["string","null"]},"index":{"type":"integer","format":"int32"},"message":{"$ref":"#/components/schemas/ChatMessage"}}},"ChatCompletionRequest":{"allOf":[{"type":["object","null"],"description":"Tolerates extra SDK fields (stream_options, logprobs, etc.)","additionalProperties":{},"propertyNames":{"type":"string"}},{"type":"object","required":["model","messages"],"properties":{"frequency_penalty":{"type":["number","null"],"format":"double"},"max_tokens":{"type":["integer","null"],"format":"int64"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/ChatMessage"}},"model":{"type":"string"},"n":{"type":["integer","null"],"format":"int32"},"presence_penalty":{"type":["number","null"],"format":"double"},"response_format":{},"seed":{"type":["integer","null"],"format":"int64"},"stop":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/StopSequence"}]},"stream":{"type":"boolean"},"temperature":{"type":["number","null"],"format":"double"},"tool_choice":{},"tools":{"type":["array","null"],"items":{}},"top_p":{"type":["number","null"],"format":"double"},"user":{"type":["string","null"]}}}],"description":"OpenAI-compatible chat completion request.\nUses `deny_unknown_fields = false` (serde default) so that SDK-specific\nfields like `stream_options`, `logprobs`, `top_logprobs`, `logit_bias`,\n`parallel_tool_calls`, etc. are silently accepted without breaking."},"ChatCompletionResponse":{"type":"object","required":["id","object","created","model","choices"],"properties":{"choices":{"type":"array","items":{"$ref":"#/components/schemas/ChatCompletionChoice"}},"created":{"type":"integer","format":"int64"},"id":{"type":"string"},"model":{"type":"string"},"object":{"type":"string"},"usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UsageInfo"}]}}},"ChatMessage":{"type":"object","required":["role"],"properties":{"content":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/MessageContent"}]},"name":{"type":["string","null"]},"role":{"type":"string"},"tool_call_id":{"type":["string","null"]},"tool_calls":{"type":["array","null"],"items":{}}}},"ChildBackupEntryResponse":{"type":"object","description":"A single child backup entry in the `GET /backups/{id}/children` response.\n\nEach entry corresponds to one `external_service_backups` row joined with\n`external_services`, providing service metadata without a second request.","required":["id","service_id","service_name","service_type","state","backup_type","started_at","s3_location","compression_type"],"properties":{"backup_type":{"type":"string","description":"Backup variant (e.g. \"full\", \"incremental\")."},"compression_type":{"type":"string","description":"Compression algorithm used (e.g. \"gzip\", \"lz4\")."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When the child backup finished, if known.","example":"2025-01-15T14:35:00.456Z"},"id":{"type":"integer","format":"int32","description":"Row ID from `external_service_backups`."},"s3_location":{"type":"string","description":"Object key or `s3://` URL where the backup data lives."},"service_id":{"type":"integer","format":"int32","description":"FK to `external_services.id`."},"service_name":{"type":"string","description":"Human-readable name of the external service (e.g. \"redis-prod\")."},"service_type":{"type":"string","description":"Service type string (e.g. \"postgres\", \"redis\", \"mongodb\", \"s3\").","example":"postgres"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the child backup in bytes, if available."},"started_at":{"type":"string","description":"When the child backup started (RFC 3339).","example":"2025-01-15T14:30:00.123Z"},"state":{"type":"string","description":"Current state: \"pending\" | \"running\" | \"completed\" | \"failed\"."}}},"ChildBackupListResponse":{"type":"object","description":"Response body for `GET /backups/{id}/children`.\n\nReturns an empty `children` list (not 404) when the parent backup has no\nchild records (e.g. control-plane backups).","required":["children"],"properties":{"children":{"type":"array","items":{"$ref":"#/components/schemas/ChildBackupEntryResponse"},"description":"Zero or more child backup entries ordered by `external_service_backups.id` ASC."}}},"CleanupExpiredBackupsRequest":{"type":"object","properties":{"expected_backup_ids":{"type":["array","null"],"items":{"type":"string"},"description":"Exact candidates returned by the dry run. Execution fails if the\nretention selection has changed since preview."}}},"CliDeviceApproveRequest":{"type":"object","required":["user_code"],"properties":{"user_code":{"type":"string"}}},"CliDeviceApproveResponse":{"type":"object","required":["user_code","status"],"properties":{"status":{"type":"string"},"user_code":{"type":"string"}}},"CliDeviceLookupResponse":{"type":"object","required":["user_code","status","expires_at"],"properties":{"client_name":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time"},"requested_ip":{"type":["string","null"]},"status":{"type":"string","description":"`pending` | `approved` | `denied` | `expired`."},"user_code":{"type":"string"}}},"CliDevicePollRequest":{"type":"object","required":["device_code"],"properties":{"device_code":{"type":"string"}}},"CliDevicePollResponse":{"oneOf":[{"type":"object","description":"Still waiting on the user to approve in the browser.","required":["status"],"properties":{"status":{"type":"string","enum":["authorization_pending"]}}},{"type":"object","description":"CLI is polling faster than the server-suggested interval.","required":["status"],"properties":{"status":{"type":"string","enum":["slow_down"]}}},{"type":"object","description":"User denied the request in the browser.","required":["status"],"properties":{"status":{"type":"string","enum":["access_denied"]}}},{"type":"object","description":"The session has expired without approval.","required":["status"],"properties":{"status":{"type":"string","enum":["expired_token"]}}},{"type":"object","description":"The session was approved; this is the only response that carries\nthe API key. The key is returned exactly once and then cleared\nfrom the session row.","required":["user_id","email","role","api_key","key_prefix","status"],"properties":{"api_key":{"type":"string"},"email":{"type":"string"},"expires_at":{"type":["string","null"],"format":"date-time"},"key_prefix":{"type":"string"},"role":{"type":"string"},"status":{"type":"string","enum":["approved"]},"user_id":{"type":"integer","format":"int32"}}}]},"CliDeviceStartRequest":{"type":"object","properties":{"client_name":{"type":["string","null"],"description":"Friendly hostname / client identifier shown in the browser approval\nscreen. Sanitized before display.","example":"dviejo-mac.local"}}},"CliDeviceStartResponse":{"type":"object","required":["device_code","user_code","verification_uri","verification_uri_complete","expires_in","interval"],"properties":{"device_code":{"type":"string","description":"Opaque secret the CLI polls with. Never display to a human."},"expires_in":{"type":"integer","format":"int64","description":"Seconds until the device_code expires."},"interval":{"type":"integer","format":"int64","description":"Suggested polling interval, in seconds."},"user_code":{"type":"string","description":"Short human-readable code the user types into the browser.","example":"ABCD-1234"},"verification_uri":{"type":"string","description":"Base verification URL — the CLI may display this when the\npre-filled URL is too long to be useful.","example":"https://temps.example.com/cli-login"},"verification_uri_complete":{"type":"string","description":"`verification_uri` with `user_code` pre-filled. Open this directly.","example":"https://temps.example.com/cli-login/ABCD-1234"}}},"CliLoginRequest":{"type":"object","required":["username","password"],"properties":{"password":{"type":"string"},"username":{"type":"string"}}},"CloudProvider":{"type":"string","description":"Cloud provider detected from node metadata","enum":["aws","gcp","azure","hetzner","digitalocean","other"]},"CloudflareConfig":{"type":"object","description":"Configuration for a Cloudflare Email Sending notification provider.\n\nNotifications are delivered through Cloudflare's transactional Email Sending\nAPI. Only the account, token, sender and recipients are configured here —\nsubject and body are derived from each notification.","required":["account_id","api_token","from_address","to_addresses"],"properties":{"account_id":{"type":"string","description":"Cloudflare account id that owns the Email Sending configuration.","example":"023e105f4ecef8ad9ca31a8372d0c353"},"api_token":{"type":"string","description":"Cloudflare API token with the Email Sending permission. Encrypted at\nrest and masked in normal API responses."},"from_address":{"type":"string","description":"Verified sender address (must belong to a domain enabled for Cloudflare\nEmail Sending).","example":"welcome@infracf.example.com"},"from_name":{"type":["string","null"],"description":"Optional human-friendly sender name shown in the recipient's inbox."},"to_addresses":{"type":"array","items":{"type":"string"},"description":"Recipients that should receive the notification."}}},"ClusterCapacity":{"type":"object","description":"Total cluster capacity (sum of node allocatable resources)","required":["node_count","cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"Total allocatable CPU in millicores"},"memory_mb":{"type":"integer","format":"int64","description":"Total allocatable memory in MB"},"node_count":{"type":"integer","description":"Number of nodes","minimum":0}}},"ClusterDnsSettings":{"type":"object","description":"Cluster-DNS resolver settings (ADR-024, experimental beta).\n\nWhen `enabled`, the Temps control plane starts a Hickory DNS resolver and\ninjects it as the first nameserver into every deployed container via\n`HostConfig.Dns` — giving containers the ability to resolve `*.temps.local`\nFQDNs for service-to-service communication. Worker nodes pick this flag up\nfrom the `/api/internal/nodes/{id}/network/peers` wire response and gate\ntheir own per-node resolver the same way.\n\n**Default: `false` (disabled).**\n\nWhy disabled by default: a production incident showed that when the injected\nHickory resolver was slow or transiently unresponsive for a non-`*.temps.local`\n(external) hostname, glibc's resolver cycled through all three nameservers\n(`172.20.0.1`, `1.1.1.1`, `8.8.8.8`) at ~5 s timeout × 2 attempts each,\ncausing 22–27 s delays for outbound TCP connections. Disabling the injection\nrestores Docker's embedded DNS as the sole resolver, eliminating that failure\nmode. Operators running single/multi-node installs that depend on\n`*.temps.local` resolution must explicitly opt in by setting `enabled: true`.\n\n`bool` defaults to `false` in Rust and JSON (`#[serde(default)]`), so the\nsafe-off behaviour is automatic for new installs and legacy settings rows.","properties":{"enabled":{"type":"boolean","description":"Master switch. When `false` (default), no custom DNS is injected into\ncontainers — they use Docker's embedded DNS which forwards to the host's\nown `resolv.conf`. When `true`, the control-plane Hickory resolver is\nstarted and its bridge IP is injected as the first nameserver so\n`*.temps.local` FQDNs resolve inside containers.","default":false,"example":false}}},"ClusterHealthReportResponse":{"type":"object","description":"Response body for `GET /external-services/{id}/cluster-health`.","required":["checked_at","monitor_response_ms","members"],"properties":{"checked_at":{"type":"string","description":"ISO-8601 wall-clock when the report was generated.","example":"2025-10-12T12:15:47.609192Z"},"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberHealthResponse"}},"monitor_error":{"type":["string","null"],"description":"Set when the monitor itself was unreachable. UI shows a banner."},"monitor_response_ms":{"type":"integer","format":"int64","description":"Round-trip to query the monitor (ms)."}}},"ClusterMemberHealthResponse":{"type":"object","description":"One row in the cluster Members table — see `GET /external-services/{id}/cluster-health`.","required":["nodename","nodehost","nodeport","reported_state","goal_state","health","seconds_since_report","candidate_priority","replication_quorum"],"properties":{"candidate_priority":{"type":"integer","format":"int32"},"goal_state":{"type":"string","description":"What the monitor *wants* the node to be. Differs from\n`reported_state` mid-transition (failover, demotion, etc.)."},"health":{"type":"integer","format":"int32","description":"pg_auto_failover liveness signal: `1` healthy, `0` unknown\n(no recent report), `-1` unhealthy."},"nodehost":{"type":"string"},"nodename":{"type":"string"},"nodeport":{"type":"integer","format":"int32"},"replay_lag_ms":{"type":["integer","null"],"format":"int64","description":"`replay_lag` from `pg_stat_replication`, in milliseconds."},"replication_quorum":{"type":"boolean"},"reported_state":{"type":"string","description":"What the node *last told the monitor* it was. Stale during outages."},"seconds_since_report":{"type":"integer","format":"int64","description":"Wall-clock seconds since the node last reported in."},"sync_state":{"type":["string","null"],"description":"`sync` / `quorum` / `async` for secondaries; `null` for the primary."}}},"ClusterMemberRequest":{"type":"object","description":"Request spec for a single cluster member.","required":["role"],"properties":{"node_id":{"type":["integer","null"],"format":"int32","description":"Target worker node ID. Omit or null to run on the control plane."},"role":{"type":"string","description":"Service-type-specific role (e.g., \"monitor\", \"primary\", \"replica\")","example":"primary"}}},"CmdBody":{"type":"object","required":["command"],"properties":{"args":{"type":"array","items":{"type":"string"},"description":"Arguments to pass to the binary. Defaults to empty."},"command":{"type":"string","description":"Binary name (argv[0]) — e.g. `\"ls\"`, `\"node\"`. The SDK sends this\nseparately from `args`."},"cwd":{"type":["string","null"],"description":"Working directory override."},"env":{"type":"object","description":"Extra env vars.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"sudo":{"type":"boolean","description":"When true, the SDK runs the command privileged. We ignore it today\n— the underlying provider always runs as the sandbox's own user."},"wait":{"type":"boolean","description":"When true, the response is an `application/x-ndjson` stream where\nthe first line is the running-command envelope and the second line\nis the finished-command envelope with `exitCode`."}}},"CmdInner":{"type":"object","description":"Inner `command` object — matches the SDK's zod validator exactly.\n`exitCode` is `null` until the command terminates; `startedAt` is Unix\nepoch milliseconds.","required":["id","name","args","cwd","sandboxId","startedAt"],"properties":{"args":{"type":"array","items":{"type":"string"}},"cwd":{"type":"string"},"exitCode":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"name":{"type":"string"},"sandboxId":{"type":"string"},"startedAt":{"type":"integer","format":"int64"}}},"CmdKillBody":{"type":"object","description":"SDK-shaped kill body. The SDK sends `{signal: AbortSignal}` but only\nuses the signal for HTTP request abortion client-side; there's no\nsignal name on the wire.","properties":{"force":{"type":"boolean","description":"Optional: when true, SIGKILL instead of SIGTERM."}}},"CmdResponse":{"type":"object","description":"`@vercel/sandbox` envelope: `{ command: {...} }`.","required":["command"],"properties":{"command":{"$ref":"#/components/schemas/CmdInner"}}},"CommitExistsResponse":{"type":"object","required":["exists"],"properties":{"commit":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CommitInfo","description":"Commit metadata when the requested SHA exists."}]},"commit_sha":{"type":["string","null"]},"exists":{"type":"boolean"}}},"CommitInfo":{"type":"object","required":["sha","message","author","author_email","date"],"properties":{"author":{"type":"string","description":"Author name"},"author_email":{"type":"string","description":"Author email"},"date":{"type":"string","format":"date-time","description":"Commit date in ISO 8601 format","example":"2025-10-12T12:15:47.609192Z"},"message":{"type":"string","description":"Commit message"},"sha":{"type":"string","description":"Commit SHA hash"}}},"CommitListResponse":{"type":"object","required":["commits"],"properties":{"commits":{"type":"array","items":{"$ref":"#/components/schemas/CommitInfo"}}}},"Comparator":{"type":"string","description":"Comparator for static/forecast threshold detectors. Serializes to the\nkeyword forms `gt|gte|lt|lte` (NOT the SQL operators used by\n`temps-monitoring::compare`).","enum":["gt","gte","lt","lte"]},"ComposePublicPort":{"type":"object","description":"A port that should be exposed publicly through the proxy for a compose service.","required":["service","port"],"properties":{"port":{"type":"integer","format":"int32","description":"Container port to expose (e.g. 8123)","minimum":0},"service":{"type":"string","description":"Compose service name (e.g. \"web\", \"clickhouse\")"}}},"ConnectionListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"sort":{"type":["string","null"]}}},"ConnectionListResponse":{"type":"object","required":["connections","total_count","page","per_page"],"properties":{"connections":{"type":"array","items":{"$ref":"#/components/schemas/ConnectionResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"total_count":{"type":"integer","minimum":0}}},"ConnectionResponse":{"type":"object","required":["id","provider_id","account_name","account_type","is_active","is_expired","syncing","synced_repository_count","health_status","consecutive_health_failures","created_at","updated_at"],"properties":{"account_name":{"type":"string"},"account_type":{"type":"string"},"consecutive_health_failures":{"type":"integer","format":"int32"},"created_at":{"type":"string","format":"date-time"},"health_message":{"type":["string","null"],"description":"Human-readable reason when health_status is \"unhealthy\"; null otherwise."},"health_status":{"type":"string","description":"Current health status: \"healthy\", \"unhealthy\", or \"unknown\"."},"id":{"type":"integer","format":"int32"},"installation_id":{"type":["string","null"]},"is_active":{"type":"boolean"},"is_expired":{"type":"boolean"},"last_health_check_at":{"type":["string","null"],"format":"date-time"},"last_synced_at":{"type":["string","null"],"format":"date-time"},"provider_id":{"type":"integer","format":"int32"},"synced_repository_count":{"type":"integer","format":"int32","description":"Running count of repositories persisted by the current (or most\nrecent) sync. Resets to 0 when a new sync begins; useful for showing\nlive progress on large syncs."},"syncing":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"},"user_id":{"type":["integer","null"],"format":"int32"}}},"ConnectionTestResult":{"type":"object","description":"Connection test result","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"ConsoleEventPayload":{"type":"object","description":"Payload for server-side event ingestion via the console API.\n\nThe app backend reads the encrypted `_temps_visitor_id` and `_temps_sid`\ncookie values from the user's request and forwards them here.\nTemps decrypts them server-side to resolve visitor/session identity.","required":["event_name","environment_id","deployment_id"],"properties":{"deployment_id":{"type":"integer","format":"int32","description":"Deployment ID to attribute the event to"},"environment_id":{"type":"integer","format":"int32","description":"Environment ID to attribute the event to"},"event_data":{"description":"Arbitrary JSON event data"},"event_name":{"type":"string","description":"Event name (e.g. \"purchase\", \"signup\", custom event names)"},"request_path":{"type":"string","description":"Page path context (defaults to \"/\")"},"request_query":{"type":"string","description":"Query string context"},"session_id":{"type":["string","null"],"description":"Encrypted `_temps_sid` cookie value from the user's browser"},"visitor_id":{"type":["string","null"],"description":"Encrypted `_temps_visitor_id` cookie value from the user's browser"}}},"ContainerActionResponse":{"type":"object","description":"Response indicating success of container state change","required":["container_id","container_name","action","status","message"],"properties":{"action":{"type":"string"},"container_id":{"type":"string"},"container_name":{"type":"string"},"message":{"type":"string"},"status":{"type":"string"}}},"ContainerDetailResponse":{"type":"object","description":"Detailed container information with environment variables and metrics","required":["id","container_id","container_name","image_name","status","deployment_id","created_at","deployed_at","container_port","environment_variables"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"container_port":{"type":"integer","format":"int32","description":"Port inside the container"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None when no limit is configured."},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"deployed_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"deployment_id":{"type":"integer","format":"int32"},"environment_variables":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarResponse"},"description":"Environment variables (sensitive values masked)"},"error_message":{"type":["string","null"],"description":"Free-form error string from Docker's container state on exit."},"exit_code":{"type":["integer","null"],"format":"int32","description":"Process exit code reported by Docker. None while still running."},"exit_reason":{"type":["string","null"],"description":"Human-readable reason the container exited."},"finished_at":{"type":["string","null"],"description":"When the container exited (Docker's FinishedAt). None while running.","example":"2025-10-12T12:16:47.609192Z"},"host_port":{"type":["integer","null"],"format":"int32","description":"Port on the host machine"},"id":{"type":"integer","format":"int32"},"image_name":{"type":"string"},"oom_killed":{"type":["boolean","null"],"description":"True when Docker's OOM killer terminated the container."},"ready_at":{"type":["string","null"],"example":"2025-10-12T12:16:47.609192Z"},"resource_limits":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourceLimitsResponse","description":"Resource limits"}]},"restart_count":{"type":["integer","null"],"format":"int64","description":"Container restart count from Docker"},"service_name":{"type":["string","null"],"description":"Compose service name (e.g. \"web\", \"redis\"). None for single-container deployments."},"service_url":{"type":["string","null"],"description":"Per-service URL for compose deployments"},"started_at":{"type":["string","null"],"description":"When the container's main process most recently started.","example":"2025-10-12T12:15:50.000000Z"},"status":{"type":"string"}}},"ContainerEnvironmentVariableValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"ContainerInfoResponse":{"type":"object","required":["container_id","container_name","image_name","status","created_at"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None when no limit is configured."},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"error_message":{"type":["string","null"],"description":"Free-form error string from Docker's container state on exit."},"exit_code":{"type":["integer","null"],"format":"int32","description":"Process exit code reported by Docker. None while still running."},"exit_reason":{"type":["string","null"],"description":"Human-readable reason the container exited (e.g. \"OOMKilled\",\n\"Killed by SIGKILL (exit code 137)\", \"Exit code 1\"). None while running."},"finished_at":{"type":["string","null"],"description":"When the container exited (Docker's FinishedAt). None while running.","example":"2025-10-12T12:16:47.609192Z"},"image_name":{"type":"string"},"node_name":{"type":["string","null"],"description":"Node name where this container is running. None for local (single-node) deployments."},"oom_killed":{"type":["boolean","null"],"description":"True when Docker's OOM killer terminated the container."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Container restart count from Docker. The UI shows a chip when this is\n> 0 so a crash loop is visible without opening detail."},"service_name":{"type":["string","null"],"description":"Compose service name (e.g. \"web\", \"redis\"). None for single-container deployments."},"service_url":{"type":["string","null"],"description":"Per-service URL for compose deployments (e.g. \"https://web-myapp.localho.st\")"},"started_at":{"type":["string","null"],"description":"When the container's main process most recently started. The UI uses\nthis for the uptime label so the count resets when a container is\nrestarted in place. None for containers that never started.","example":"2025-10-12T12:15:50.000000Z"},"status":{"type":"string"}}},"ContainerInventoryItem":{"type":"object","description":"A container reported by the agent during heartbeat reconciliation.","required":["container_id","container_name"],"properties":{"container_id":{"type":"string","description":"Docker container ID"},"container_name":{"type":"string","description":"Docker container name"}}},"ContainerListResponse":{"type":"object","required":["containers","total"],"properties":{"containers":{"type":"array","items":{"$ref":"#/components/schemas/ContainerInfoResponse"}},"total":{"type":"integer","minimum":0}}},"ContainerLogSettings":{"type":"object","description":"Docker container log rotation settings\nControls the `--log-opt max-size` and `--log-opt max-file` for containers","properties":{"max_file":{"type":"integer","format":"int32","description":"Maximum number of rotated log files to keep (e.g., 3 means up to 3 x max_size total)","default":3,"example":3,"minimum":0},"max_size":{"type":"string","description":"Maximum size of each log file (e.g., \"50m\", \"100m\", \"1g\")\nDocker default is unlimited; we default to \"50m\" to prevent disk exhaustion","default":"50m","example":"50m"},"service_max_file":{"type":"integer","format":"int32","description":"Maximum rotated log files for external service containers","default":3,"example":3,"minimum":0},"service_max_size":{"type":"string","description":"Maximum size for external service container logs (postgres, redis, etc.)\nDefaults to \"20m\" since services are typically less verbose than app containers","default":"20m","example":"20m"}}},"ContainerLogsQuery":{"type":"object","properties":{"container_name":{"type":["string","null"],"description":"Optional container name to get logs from (if deployment has multiple containers)"},"end_date":{"type":["integer","null"],"format":"int64"},"follow":{"type":"boolean","description":"Follow log output in real-time (default: true for backward compatibility)"},"start_date":{"type":["integer","null"],"format":"int64"},"tail":{"type":["string","null"]},"timestamps":{"type":"boolean","description":"Include timestamps in log output (default: false)"}}},"ContainerMetricHistoryPoint":{"type":"object","description":"One bucketed data point of a container resource metric time series.","required":["time","value"],"properties":{"time":{"type":"string","description":"Bucket timestamp (ISO 8601 with `Z` suffix).","example":"2025-10-12T12:15:00+00:00"},"value":{"type":"number","format":"double","description":"Averaged metric value for the bucket."}}},"ContainerMetricsHistoryQuery":{"type":"object","description":"Query parameters for the container metrics history endpoint.","required":["metric"],"properties":{"metric":{"type":"string","description":"Dotted metric name, e.g. `container.cpu_percent` or\n`container.memory_used_bytes`."},"range":{"type":"string","description":"Time window: `1h`, `6h`, `24h`, or `7d` (defaults to `1h`)."}}},"ContainerMetricsResponse":{"type":"object","description":"Container resource metrics (CPU, memory usage)","required":["container_id","container_name","cpu_percent","memory_bytes","network_rx_bytes","network_tx_bytes","timestamp"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None = no limit."},"cpu_percent":{"type":"number","format":"double","description":"CPU usage as a multi-core percentage (Docker convention: 200 = 2 cores\nfully pinned). Divide by 100 to get cores used."},"memory_bytes":{"type":"integer","format":"int64","description":"Memory usage in bytes","minimum":0},"memory_limit_bytes":{"type":["integer","null"],"format":"int64","description":"Memory limit in bytes (if set)","minimum":0},"memory_percent":{"type":["number","null"],"format":"double","description":"Memory usage percentage (0-100) if limit is set"},"network_rx_bytes":{"type":"integer","format":"int64","description":"Network bytes received","minimum":0},"network_tx_bytes":{"type":"integer","format":"int64","description":"Network bytes transmitted","minimum":0},"timestamp":{"type":"string","description":"Timestamp of metrics collection","example":"2025-10-12T12:15:47.609192Z"}}},"ContainerResponse":{"type":"object","required":["name","container_type","can_contain_containers","can_contain_entities","metadata"],"properties":{"can_contain_containers":{"type":"boolean","description":"Can this container hold other containers?","example":true},"can_contain_entities":{"type":"boolean","description":"Can this container hold entities (tables, collections, etc.)?","example":false},"child_container_type":{"type":["string","null"],"description":"Type of child containers (if can_contain_containers is true)","example":"schema"},"container_type":{"type":"string","description":"Container type (database, schema, keyspace, bucket, etc.)","example":"database"},"entity_count_hint":{"type":["string","null"],"description":"Hint for UI on expected entity count (small = sidebar, large = pagination)","example":"large"},"entity_type_label":{"type":["string","null"],"description":"Label for entity type (if can_contain_entities is true)","example":"table"},"metadata":{"description":"Additional metadata"},"name":{"type":"string","description":"Container name","example":"mydb"}}},"ContainerRuntimeInfo":{"type":"object","description":"Snapshot of a container's lifecycle state from `docker inspect`.\n`restart_count` and `oom_killed` are the load-bearing fields when\ndiagnosing crash loops — the kernel OOM killer never reaches the\napplication's logs, so seeing `oom_killed=true` is the only signal\nthat a memory limit was the cause.","required":["role","container_name","resource_limits"],"properties":{"container_id":{"type":["string","null"],"description":"Container Docker id, when present. None = container does not exist\n(was never created or was removed externally)."},"container_name":{"type":"string","description":"Stable name of the Docker container (e.g. `postgres-mydb`)."},"exit_code":{"type":["integer","null"],"format":"int64","description":"Last container exit code, when known. Non-zero = unclean stop."},"finished_at":{"type":["string","null"],"description":"ISO-8601 timestamp of the most recent termination, when known."},"image":{"type":["string","null"],"description":"Currently-effective Docker image (e.g. `gotempsh/postgres-walg:18-bookworm`)."},"oom_killed":{"type":["boolean","null"],"description":"True when the container's last termination was caused by the\nkernel OOM killer. Set if the user enabled hard memory limits\nand the working set exceeded them."},"resource_limits":{"$ref":"#/components/schemas/ServiceResourceLimits","description":"Currently-applied resource limits read off the container's\n`HostConfig`. Compare this against the user-configured limits to\ndetect drift (an old container that never picked up new caps)."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Total restarts since the container was created. Useful for\ndetecting crash loops — a steady stream means something is killing\nthe container repeatedly (frequently OOM)."},"role":{"type":"string","description":"`service_members.role` for cluster members; \"standalone\" otherwise."},"started_at":{"type":["string","null"],"description":"ISO-8601 timestamp of when the container last started. None when\nit has never started (i.e. created but never run)."},"status":{"type":["string","null"],"description":"Bollard container state (\"running\", \"exited\", \"dead\", etc.). None\nwhen the container does not exist."}}},"ContainerStatsSample":{"type":"object","description":"Live resource usage sample for a single container.\n\n`cpu_percent` is computed by Docker's standard formula:\n ((cpu_delta / system_delta) * online_cpus) * 100\n`memory_percent` is `(memory_usage / memory_limit) * 100` — when no\nmemory limit is set the limit reported by Docker is the host's total\nRAM, so a 5% reading means \"5% of host RAM\", not \"5% of allocated\".","required":["role","container_name"],"properties":{"container_name":{"type":"string"},"cpu_percent":{"type":["number","null"],"format":"double","description":"CPU usage as a percentage. `None` when the container is not running\n(Docker returns no usable counters)."},"memory_limit_bytes":{"type":["integer","null"],"format":"int64","description":"Memory limit in bytes (host RAM if no limit set).","minimum":0},"memory_percent":{"type":["number","null"],"format":"double","description":"Memory usage as a percentage of `memory_limit_bytes`."},"memory_usage_bytes":{"type":["integer","null"],"format":"int64","description":"Resident memory usage in bytes.","minimum":0},"online_cpus":{"type":["integer","null"],"format":"int32","description":"Number of cores Docker observed at sample time. Used by the UI\nto label \"x/y cores\" instead of just a percent.","minimum":0},"role":{"type":"string"}}},"ContentPart":{"type":"object","required":["type"],"properties":{"image_url":{},"text":{"type":["string","null"]},"type":{"type":"string"}}},"ContextLine":{"type":"object","description":"A line in context response","required":["timestamp","level","message","line_offset","is_match"],"properties":{"fields":{},"is_match":{"type":"boolean","description":"Whether this line matched the original search"},"level":{"$ref":"#/components/schemas/LogLevel"},"line_offset":{"type":"integer","format":"int32"},"message":{"type":"string"},"timestamp":{"type":"string"}}},"ContextLogsRequest":{"type":"object","required":["chunk_id","line_offset"],"properties":{"chunk_id":{"type":"string"},"line_offset":{"type":"integer","format":"int32"},"lines":{"type":["integer","null"],"format":"int32","description":"Number of context lines before and after (default: 25)","minimum":0}}},"ContextLogsResponse":{"type":"object","required":["lines","target_index"],"properties":{"lines":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"}},"target_index":{"type":"integer","minimum":0}}},"ConversationDetailResponse":{"allOf":[{"$ref":"#/components/schemas/ConversationResponse"},{"type":"object","required":["messages"],"properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/MessageResponse"},"description":"Turns oldest-first. The `system` seed message is omitted (internal)."}}}]},"ConversationResponse":{"type":"object","required":["public_id","context_type","context_id","status","created_at","last_activity_at"],"properties":{"context_id":{"type":"string"},"context_type":{"type":"string"},"created_at":{"type":"string"},"last_activity_at":{"type":"string"},"public_id":{"type":"string"},"status":{"type":"string"},"title":{"type":["string","null"]}}},"ConversationSummary":{"type":"object","description":"A conversation summary grouping related AI invocations.","required":["conversation_id","message_count","total_input_tokens","total_output_tokens","total_tokens","total_cost_microcents","avg_latency_ms","models_used","first_at","last_at"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"conversation_id":{"type":"string"},"first_at":{"type":"string"},"last_at":{"type":"string"},"message_count":{"type":"integer","format":"int64"},"models_used":{"type":"array","items":{"type":"string"}},"total_cost_microcents":{"type":"integer","format":"int64"},"total_input_tokens":{"type":"integer","format":"int64"},"total_output_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"ConversationsQueryParams":{"type":"object","properties":{"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"limit":{"type":["integer","null"],"format":"int64","description":"Max results (defaults to 50, max 100)","minimum":0},"model":{"type":["string","null"],"description":"Filter by model name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"CopyBlobRequest":{"type":"object","description":"Request to copy a blob","required":["fromUrl","toPathname"],"properties":{"fromUrl":{"type":"string","description":"Source blob URL or pathname","example":"/api/blob/10/images/avatar.png"},"projectId":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"toPathname":{"type":"string","description":"Destination pathname","example":"images/avatar-copy.png"}}},"CostAnalysis":{"type":"object","description":"Full cluster cost + rightsizing analysis attached to an import plan.","required":["nodes","capacity","requested","usage_source","overprovisioning","recommendation","notes"],"properties":{"actual_usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourceFootprint","description":"Measured usage from the metrics API (`metrics.k8s.io`).\n`None` when metrics-server is not installed."}]},"capacity":{"$ref":"#/components/schemas/ClusterCapacity","description":"Total cluster capacity (sum of node allocatable resources)"},"control_plane_monthly_usd":{"type":["number","null"],"format":"double","description":"Managed control-plane fee included in `current_monthly_usd` (EKS/GKE\ncharge ~$73/mo per cluster). `None` when not applicable/unknown."},"current_monthly_usd":{"type":["number","null"],"format":"double","description":"Estimated total infrastructure cost per month in USD (compute nodes +\ncontrol-plane fee). `None` when no node could be priced."},"nodes":{"type":"array","items":{"$ref":"#/components/schemas/NodeCostInfo"},"description":"Per-node inventory with price estimates where the instance type is known"},"notes":{"type":"array","items":{"type":"string"},"description":"Honesty notes: what could not be measured, which numbers are\nestimates, and any assumptions made. Always shown to the user."},"overprovisioning":{"$ref":"#/components/schemas/OverprovisioningAssessment","description":"Requests-vs-capacity-vs-usage assessment"},"provider":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CloudProvider","description":"Detected cloud provider (from node `providerID` prefixes)"}]},"recommendation":{"$ref":"#/components/schemas/TargetRecommendation","description":"The temps/Hetzner target sizing and savings estimate"},"requested":{"$ref":"#/components/schemas/ResourceFootprint","description":"Sum of pod resource *requests* across running pods — what the\nscheduler has reserved, i.e. what the cluster is sized for."},"usage_source":{"$ref":"#/components/schemas/UsageSource","description":"How the usage numbers were obtained (drives UI wording)"}}},"CreateAlertRuleRequest":{"type":"object","required":["name","trigger_type"],"properties":{"cooldown_minutes":{"type":"integer","format":"int32","description":"Minimum minutes between notifications for same rule+group"},"enabled":{"type":"boolean"},"environment_filter":{"type":["integer","null"],"format":"int32","description":"Optional environment ID to filter alerts"},"error_level_filter":{"type":["string","null"],"description":"Optional error type/level filter"},"name":{"type":"string"},"notification_priority":{"type":"string","description":"Notification priority: Low, Normal, High, Critical"},"trigger_config":{"description":"Trigger-specific configuration (e.g., {\"count\": 100, \"window_minutes\": 60} for frequency)"},"trigger_type":{"type":"string","description":"Trigger type: new_issue, regression, frequency, new_user, user_count, status_change"}}},"CreateApiKeyRequest":{"type":"object","required":["name","role_type"],"properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["projects:read","deployments:read"]},"role_type":{"type":"string","example":"admin"}}},"CreateApiKeyResponse":{"type":"object","required":["id","name","key_prefix","role_type","api_key","created_at"],"properties":{"api_key":{"type":"string"},"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"key_prefix":{"type":"string"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"role_type":{"type":"string"}}},"CreateBackupScheduleRequest":{"type":"object","required":["name","backup_type","retention_period","schedule_expression","enabled","tags"],"properties":{"backup_type":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"include_control_plane":{"type":["boolean","null"],"description":"When `true` (default), every run also produces a `control_plane`\nbackup of Temps's own database. Operators who use Temps purely as\na backup orchestrator for external DBs can set this to `false` to\nkeep the run history focused on those services."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Optional wall-clock timeout override for jobs created by this schedule\n(seconds). When set, overrides the engine-family default. `null` means\n\"use engine default.\" The per-job `max_runtime_secs` in\n`EnqueueJobParams` can still override this for ad-hoc triggers."},"name":{"type":"string"},"retention_period":{"type":"integer","format":"int32"},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"Optional S3 source. If omitted, the current default S3 source is used."},"schedule_expression":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"target_all_services":{"type":["boolean","null"],"description":"When `true` (default), the schedule backs up every external service\non the host — including databases created in the future. When\n`false`, the schedule backs up only the services explicitly attached\nvia `POST /backups/schedules/{id}/services`. Omit to use the default."}}},"CreateBitbucketRequest":{"type":"object","required":["name","auth"],"properties":{"auth":{"$ref":"#/components/schemas/BitbucketAuthInput","description":"Authentication credentials — either an access token or an app password."},"name":{"type":"string","description":"Display name for this provider."}}},"CreateCloudflareProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/CloudflareConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateConversationRequest":{"type":"object","required":["context_type","context_id"],"properties":{"context_id":{"type":"string","description":"The entity id (ints stringified)."},"context_type":{"type":"string","description":"e.g. `\"deployment\"`."}}},"CreateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"name":{"type":["string","null"]}}},"CreateDashboardRequest":{"type":"object","required":["project_id","name","layout"],"properties":{"layout":{"$ref":"#/components/schemas/DashboardLayout"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"}}},"CreateDeploymentTokenRequest":{"type":"object","required":["name"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment ID - if set, token is scoped to a specific deployment"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID - if not set, token applies to all environments"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"},"description":"List of permissions (e.g., [\"visitors:enrich\", \"emails:send\"])\nIf not provided, defaults to full access","example":["visitors:enrich","emails:send"]}}},"CreateDeploymentTokenResponse":{"type":"object","required":["id","project_id","name","token_prefix","token","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"project_id":{"type":"integer","format":"int32"},"token":{"type":"string","description":"The full token value - only returned on creation"},"token_prefix":{"type":"string"}}},"CreateDnsProviderRequest":{"type":"object","description":"Request to create a new DNS provider","required":["name","provider_type","credentials"],"properties":{"credentials":{"$ref":"#/components/schemas/DnsProviderCredentials","description":"Provider credentials"},"description":{"type":["string","null"],"description":"Optional description"},"name":{"type":"string","description":"User-friendly name","example":"My Cloudflare"},"provider_type":{"$ref":"#/components/schemas/DnsProviderType","description":"Provider type"}}},"CreateDomainRequest":{"type":"object","required":["domain"],"properties":{"challenge_type":{"type":"string","description":"Challenge type for Let's Encrypt validation. Options: \"http-01\" (default) or \"dns-01\""},"domain":{"type":"string"}}},"CreateEmailDomainRequest":{"type":"object","required":["provider_id","domain"],"properties":{"domain":{"type":"string","description":"Domain name (e.g., \"updates.example.com\")","example":"updates.example.com"},"provider_id":{"type":"integer","format":"int32","description":"Provider ID to use for this domain"}}},"CreateEmailProviderRequest":{"type":"object","required":["name","provider_type","region"],"properties":{"name":{"type":"string","description":"User-friendly name for the provider","example":"My AWS SES"},"provider_type":{"$ref":"#/components/schemas/EmailProviderTypeRoute","description":"Provider type"},"region":{"type":"string","description":"Cloud region. For SMTP this is informational only — the host/port carry the real routing.","example":"us-east-1"},"scaleway_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ScalewayCredentialsRequest","description":"Scaleway credentials (required if provider_type is scaleway)"}]},"ses_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SesCredentialsRequest","description":"AWS SES credentials (required if provider_type is ses)"}]},"smtp_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SmtpCredentialsRequest","description":"Generic SMTP credentials (required if provider_type is smtp). Use when\nyou only have SMTP creds and want to import an already-set-up domain."}]},"sns_topic_arn":{"type":["string","null"],"description":"Exact SNS topic allowed to deliver SES events for this provider."}}},"CreateEnvironmentRequest":{"type":"object","required":["name","branch"],"properties":{"branch":{"type":"string"},"name":{"type":"string"},"set_as_preview":{"type":"boolean","description":"If true, set this environment as the preview environment for the project"}}},"CreateEnvironmentVariableRequest":{"type":"object","required":["key","value","environment_ids"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean","description":"Include this environment variable in preview environments (default: true)"},"is_secret":{"type":"boolean","description":"When true the variable is treated as write-only: never returned in\nplaintext from the API, masked in the UI, and updates that omit the\nvalue preserve the existing ciphertext. The flag is one-way — secret\nvars cannot be demoted back to regular vars."},"key":{"type":"string"},"value":{"type":"string"}}},"CreateExternalServiceRequest":{"type":"object","required":["name","service_type","parameters"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberRequest"},"description":"Cluster member specifications. Required when topology is \"cluster\"."},"name":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Target node ID for the service. Omit or null to run on the control plane."},"parameters":{"type":"object","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"},"topology":{"type":"string","description":"Service topology: \"standalone\" (default) or \"cluster\" (HA multi-member).","example":"standalone"},"version":{"type":["string","null"]}}},"CreateFunnelRequest":{"type":"object","required":["name","steps"],"properties":{"description":{"type":["string","null"]},"name":{"type":"string"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/CreateFunnelStep"}}}},"CreateFunnelResponse":{"type":"object","required":["funnel_id","message"],"properties":{"funnel_id":{"type":"integer","format":"int32"},"message":{"type":"string"}}},"CreateFunnelStep":{"type":"object","required":["event_name"],"properties":{"event_filter":{"type":"array","items":{"$ref":"#/components/schemas/SmartFilter"}},"event_name":{"type":"string"}}},"CreateGenericRequest":{"type":"object","required":["name","clone_url"],"properties":{"base_url":{"type":["string","null"],"description":"Optional base URL of the git host for display purposes (no API is called)."},"clone_url":{"type":"string","description":"HTTPS clone URL for the repository, e.g. `https://git.example.com/org/repo.git`."},"name":{"type":"string","description":"Display name for this provider."},"token":{"type":["string","null"],"description":"Access token or password. Omit (or set to `null`) for public repositories."},"token_username":{"type":["string","null"],"description":"HTTP Basic username used with the token. Defaults to `x-access-token` when\nabsent or empty. Ignored for public (unauthenticated) repositories."}}},"CreateGitHubPATRequest":{"type":"object","required":["name","token"],"properties":{"name":{"type":"string"},"token":{"type":"string"}}},"CreateGitLabOAuthRequest":{"type":"object","required":["name","client_id","client_secret","redirect_uri"],"properties":{"base_url":{"type":["string","null"]},"client_id":{"type":"string"},"client_secret":{"type":"string"},"name":{"type":"string"},"redirect_uri":{"type":"string"}}},"CreateGitLabPATRequest":{"type":"object","required":["name","token"],"properties":{"base_url":{"type":["string","null"]},"name":{"type":"string"},"token":{"type":"string"}}},"CreateGiteaPATRequest":{"type":"object","required":["name","token","base_url"],"properties":{"base_url":{"type":"string","description":"HTTPS base URL of the Gitea instance, e.g. `https://git.example.com`."},"name":{"type":"string","description":"Display name for this provider."},"token":{"type":"string","description":"Personal access token issued by the Gitea instance."}}},"CreateIncidentRequest":{"type":"object","required":["title","severity"],"properties":{"description":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"monitor_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"title":{"type":"string"}}},"CreateIntegrationBody":{"type":"object","required":["provider","signing_secret"],"properties":{"provider":{"type":"string","description":"Registered provider name, e.g. \"stripe\"."},"signing_secret":{"type":"string","description":"Signing secret from the provider's dashboard."}}},"CreateIpAccessControlRequest":{"type":"object","description":"Request to create an IP access control rule","required":["ip_address","action"],"properties":{"action":{"type":"string","description":"Action to take: \"block\" or \"allow\"","example":"block"},"ip_address":{"type":"string","description":"IP address in CIDR notation (e.g., \"192.168.1.1\" or \"10.0.0.0/24\")","example":"192.168.1.100"},"reason":{"type":["string","null"],"description":"Optional reason for the action","example":"Malicious activity detected"}}},"CreateMcpRequest":{"type":"object","required":["slug","name","config"],"properties":{"config":{"type":"object"},"description":{"type":["string","null"]},"name":{"type":"string"},"slug":{"type":"string"}}},"CreateMetricAlertRequest":{"type":"object","required":["project_id","name","metric_name","aggregation","detection_config","window_secs","for_duration_secs","severity","enabled"],"properties":{"aggregation":{"type":"string","description":"One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"The detector: a discriminated union keyed by `kind`. Today only\n`{ \"kind\": \"static\", \"comparator\": \"gt\", \"threshold\": 500 }` is evaluable."},"dynamic_alerts":{"type":"boolean","description":"When true (and `group_by` is set) fire one independent alarm per breaching\nseries. Static detectors only. Default false."},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32"},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys to break the metric down by, e.g. `[\"endpoint\",\"region\"]`. Empty\n(the default) = one aggregate stream. Max 2 keys; keys must match\n`[a-zA-Z0-9_.:-]`."},"grouped_notification_threshold":{"type":"integer","format":"int32","description":"When more than this many series transition to firing in the same tick, only\nthe first gets the expensive chart/AI enrichment. Range 1–1000, default 5."},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters: `[[\"key\",\"value\"],…]`. Empty = no\nfiltering (the default). Max 10 pairs; keys must match `[a-zA-Z0-9_.:-]`;\nvalues capped at 500 characters."},"max_series":{"type":"integer","format":"int32","description":"Cardinality cap for dynamic alerting: at most this many series (top by\n`|value|`). Range 1–100, default 20."},"metric_name":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"severity":{"type":"string","description":"One of `info|warning|critical`."},"window_secs":{"type":"integer","format":"int32"}}},"CreateMonitorRequest":{"type":"object","required":["name","monitor_type","environment_id"],"properties":{"check_interval_seconds":{"type":["integer","null"],"format":"int32"},"check_path":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"monitor_type":{"type":"string"},"name":{"type":"string"}}},"CreateNotificationEmailProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/EmailConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateOidcProviderRequest":{"type":"object","required":["name","issuer_url","client_id","client_secret"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"default_role":{"type":"string"},"enabled":{"type":"boolean"},"group_claim":{"type":"string"},"issuer_url":{"type":"string"},"jit_provisioning":{"type":"boolean"},"name":{"type":"string"},"role_claim":{"type":"string"},"scopes":{"type":"string"},"template":{"type":"string"},"trust_idp_email":{"type":"boolean","description":"Defaults false. Set to true only for IdPs where an admin\ncontrols user provisioning (corporate Okta, Azure AD) and\nself-signup of arbitrary emails is not possible — see the\n`trust_idp_email` field on `oidc_providers::Model` for the\nsecurity tradeoff this enables."}}},"CreateOidcRoleMappingRequest":{"type":"object","required":["priority","idp_group","role"],"properties":{"idp_group":{"type":"string"},"priority":{"type":"integer","format":"int32"},"role":{"type":"string"}}},"CreatePlanRequest":{"type":"object","description":"Request to create an import plan","required":["source","workload_id"],"properties":{"credentials":{"$ref":"#/components/schemas/ImportCredentials","description":"Platform credentials (required for cloud platforms like Vercel, Railway)"},"repository_id":{"type":["integer","null"],"format":"int32","description":"Optional repository ID to associate with the import\nIf provided, preset will be detected from the repository"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source to import from"},"workload_id":{"$ref":"#/components/schemas/WorkloadId","description":"Workload ID to import"}}},"CreatePlanResponse":{"type":"object","description":"Response with created plan","required":["session_id","plan","validation","can_execute"],"properties":{"can_execute":{"type":"boolean","description":"Whether the plan can be executed"},"plan":{"$ref":"#/components/schemas/ImportPlan","description":"Generated import plan"},"session_id":{"type":"string","description":"Session ID for tracking"},"validation":{"$ref":"#/components/schemas/ValidationReport","description":"Validation report"}}},"CreatePrResponse":{"type":"object","required":["run","pr_url","pr_number","branch_name"],"properties":{"branch_name":{"type":"string"},"pr_number":{"type":"integer","format":"int32"},"pr_url":{"type":"string"},"run":{"$ref":"#/components/schemas/AutofixerRunResponse"}}},"CreateProjectFromTemplateRequest":{"type":"object","description":"Request to create a project from a template\n\nSupports two deploy modes:\n * **Fork mode** — when `git_provider_connection_id` is set, the template\n repo is cloned into a new repository under the user's Git account and the\n project tracks that fork (git-push deploys, automatic deploy on push).\n * **One-click public-repo mode** — when `git_provider_connection_id` is\n omitted, the project deploys directly from the template's public source\n repository (no fork, no Git account required). This is the activation\n path: a brand-new user with no Git provider connected can still deploy a\n demo in one click. `repository_name` / `repository_owner` are ignored in\n this mode, and automatic-deploy-on-push is unavailable (there is no fork\n to receive webhooks).","required":["template_slug","project_name"],"properties":{"automatic_deploy":{"type":"boolean","description":"Enable automatic deployment on push (defaults to true). Only honoured in\nfork mode; public-repo deploys cannot receive push webhooks."},"environment_variables":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarInput"},"description":"Environment variables to set (key-value pairs)"},"git_provider_connection_id":{"type":["integer","null"],"format":"int32","description":"Git provider connection ID. When omitted, the project deploys directly\nfrom the template's public source repository instead of forking it."},"private":{"type":"boolean","description":"Whether to make the repository private (defaults to true)"},"project_name":{"type":"string","description":"Name for the new project"},"repository_name":{"type":["string","null"],"description":"Name for the new repository to create. Required in fork mode; ignored in\none-click public-repo mode."},"repository_owner":{"type":["string","null"],"description":"Owner/organization for the new repository (defaults to authenticated user)"},"storage_service_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"External storage service IDs to attach to the project"},"template_slug":{"type":"string","description":"Template slug to use as the base"}}},"CreateProjectFromTemplateResponse":{"type":"object","description":"Response after creating a project from template","required":["project_id","project_slug","project_name","repository_url","template_slug","message"],"properties":{"message":{"type":"string","description":"Message with additional info"},"project_id":{"type":"integer","format":"int32","description":"ID of the created project"},"project_name":{"type":"string","description":"Name of the created project"},"project_slug":{"type":"string","description":"Slug of the created project"},"repository_url":{"type":"string","description":"URL of the created repository"},"template_slug":{"type":"string","description":"Template that was used"}}},"CreateProjectRequest":{"type":"object","required":["name","directory","main_branch","preset","storage_service_ids"],"properties":{"automatic_deploy":{"type":["boolean","null"]},"build_command":{"type":["string","null"]},"custom_domain":{"type":["string","null"]},"directory":{"type":"string"},"environment_variables":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]}},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container (fallback when image has no EXPOSE directive)\n\nPriority order for port resolution:\n1. Image EXPOSE directive (auto-detected from built image)\n2. Environment-level exposed_port (overrides this value per environment)\n3. This project-level exposed_port (fallback)\n4. Default: 3000\n\nOnly set this if your image doesn't use EXPOSE directive.","example":8080},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"]},"install_command":{"type":["string","null"]},"is_on_demand":{"type":["boolean","null"]},"is_public_repo":{"type":["boolean","null"]},"is_web_app":{"type":["boolean","null"]},"main_branch":{"type":"string"},"name":{"type":"string"},"output_dir":{"type":["string","null"]},"performance_metrics_enabled":{"type":"boolean"},"preset":{"type":"string"},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration\n\nDifferent presets accept different configuration options:\n- **Dockerfile preset**: Accepts `DockerfilePresetConfig` with `dockerfile_path` and `build_context`\n- **Nixpacks preset**: Accepts ordered `providers` (for example `[\"...\", \"python\"]`)\n and optional inline `nixpacksConfig` TOML\n- **Static presets** (Vite, Next.js, etc.): Accept `StaticPresetConfig` with build commands and output dir\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"project_type":{"type":["string","null"]},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"source_type":{"$ref":"#/components/schemas/SourceType","description":"Source type for deployments\n\nDetermines how the project is deployed:\n- **git** (default): Traditional Git-based deployments - source code is pulled, built, and deployed\n- **docker_image**: Deploy pre-built Docker images from external registries (DockerHub, GHCR, etc.)\n- **static_files**: Deploy pre-built static files uploaded as tar.gz or zip bundles\n\nFor `docker_image` and `static_files` source types, `repo_name` and `repo_owner` are optional."},"storage_service_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"use_default_wildcard":{"type":["boolean","null"]}}},"CreateProjectSecretRequest":{"type":"object","description":"Request to create a new project secret.\n\nProject secrets are mounted into the container as files under\n`/run/secrets/` (mode 0400, tmpfs) instead of as environment variables.\nValues are always encrypted at rest and never returned in plaintext from\nthe API after create. Distinct from agent secrets (global `/settings/secrets`).","required":["key","value"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean","description":"Include this secret in preview environments."},"key":{"type":"string","description":"Identifier for the secret. Becomes the filename at `/run/secrets/`.\nMust start with a letter or underscore and contain only A-Z, a-z, 0-9, _."},"value":{"type":"string","description":"Plaintext value, <= 1 MiB."}}},"CreateProviderKeyRequest":{"type":"object","required":["provider","display_name","api_key"],"properties":{"api_key":{"type":"string"},"base_url":{"type":["string","null"]},"default_model":{"type":["string","null"],"description":"Optional model id to pin for this provider (e.g. \"gpt-4o-mini\")."},"display_name":{"type":"string"},"provider":{"type":"string"}}},"CreateProviderRequest":{"type":"object","required":["name","provider_type","config"],"properties":{"config":{},"enabled":{"type":["boolean","null"]},"name":{"type":"string"},"provider_type":{"type":"string"}}},"CreateRouteRequest":{"type":"object","required":["domain","host","port"],"properties":{"domain":{"type":"string"},"host":{"type":"string"},"port":{"type":"integer","format":"int32"},"route_type":{"type":["string","null"],"description":"Route type: \"http\" (default) matches on HTTP Host header,\n\"tls\" matches on TLS SNI hostname for TCP passthrough"}}},"CreateS3SourceRequest":{"type":"object","required":["name","bucket_name","bucket_path","access_key_id","secret_key","region"],"properties":{"access_key_id":{"type":"string"},"bucket_name":{"type":"string"},"bucket_path":{"type":"string"},"endpoint":{"type":["string","null"],"description":"Optional endpoint URL for S3-compatible services like MinIO","example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"],"description":"Whether to use path-style addressing (default: true)","example":true},"is_default":{"type":["boolean","null"],"description":"When true, make this the default source (will swap out any existing default).\nThe very first S3 source is always created as default regardless of this flag.","example":false},"name":{"type":"string"},"region":{"type":"string"},"secret_key":{"type":"string"}}},"CreateSandboxBody":{"type":"object","properties":{"_runtime":{"type":["string","null"]},"backend":{"type":["string","null"],"description":"Isolation backend: `\"docker\"` (default) or `\"firecracker\"` (ADR-029,\nhardware-virtualized microVM — requires a host provisioned with\n`temps firecracker setup`). Omit for the platform default; existing\nclients are unaffected. Requesting an unavailable backend fails with\n400 rather than silently downgrading isolation."},"cpu_limit":{"type":["number","null"],"format":"double"},"disk_size_mb":{"type":["integer","null"],"format":"int64","description":"Root disk size in MB (Firecracker only; Docker ignores it). Omit for\nthe platform default (1 GiB).","minimum":0},"env":{"type":"object","description":"Extra env vars baked into the container on create.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"image":{"type":["string","null"],"description":"Docker image override. `null` uses the platform default."},"memory_limit_mb":{"type":["integer","null"],"format":"int64","minimum":0},"name":{"type":["string","null"]},"networkPolicy":{},"pids_limit":{"type":["integer","null"],"format":"int64"},"ports":{"type":"array","items":{"type":"integer","format":"int32","minimum":0},"description":"Ports the sandbox will listen on. Each port becomes a `routes[]`\nentry in the create/get response so `@vercel/sandbox`'s\n`sandbox.domain(port)` can resolve it client-side without an\nextra round-trip."},"preview_password":{"type":["string","null"],"description":"Optional preview-URL password. When set, every preview URL served\nfor this sandbox is gated behind a login form. 8–256 characters.\nOmit to leave preview URLs open (the sandbox ID remains the only\ngate). The plaintext is never returned; only the last-4 hint is\nsurfaced in `SandboxResponse.preview_password_hint`."},"projectId":{"type":["string","null"]},"resources":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourcesBody","description":"`@vercel/sandbox`'s nested resources object. When present, its\n`memory` / `vcpus` populate `memory_limit_mb` / `cpu_limit` if those\nweren't sent directly."}]},"source":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SourceBody","description":"Optional initial content to seed into the work dir. Clones a\nrepo or extracts a tarball after the sandbox is created."}]},"timeout":{"type":["integer","null"],"format":"int64","description":"Idle timeout as sent by `@vercel/sandbox` (milliseconds). Converted\nto seconds when `timeout_secs` is absent.","minimum":0},"timeout_secs":{"type":["integer","null"],"format":"int64","description":"Idle timeout in seconds (temps-native). Clamped to `[60, 86400]`.","minimum":0}}},"CreateSkillRequest":{"type":"object","required":["slug","name","content"],"properties":{"content":{"type":"string"},"description":{"type":["string","null"]},"name":{"type":"string"},"slug":{"type":"string"}}},"CreateSlackProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/SlackConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateUserRequest":{"type":"object","required":["username","roles"],"properties":{"email":{"type":["string","null"]},"password":{"type":["string","null"]},"roles":{"type":"array","items":{"type":"string"}},"username":{"type":"string"}}},"CreateWebhookProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/WebhookConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateWebhookRequestBody":{"type":"object","required":["url","events"],"properties":{"enabled":{"type":["boolean","null"],"description":"Whether the webhook is enabled","default":true},"events":{"type":"array","items":{"type":"string"},"description":"Event types to subscribe to","example":["deployment.created","deployment.succeeded"]},"secret":{"type":["string","null"],"description":"Secret for HMAC signature verification (optional)"},"url":{"type":"string","description":"Target URL for webhook delivery","example":"https://example.com/webhook"}}},"CreatedResource":{"type":"object","description":"Resource created during import (for rollback / audit)","required":["resource_type","resource_id","resource_name"],"properties":{"resource_id":{"type":"integer","format":"int32","description":"Resource ID"},"resource_name":{"type":"string","description":"Resource name"},"resource_type":{"type":"string","description":"Resource type (project, environment, deployment, service, domain, etc.)"}}},"CronExecutionInfo":{"type":"object","required":["id","cron_id","executed_at","url","status_code","headers","response_time_ms"],"properties":{"cron_id":{"type":"integer","format":"int32"},"error_message":{"type":["string","null"]},"executed_at":{"type":"string"},"headers":{"type":"string"},"id":{"type":"integer","format":"int32"},"response_time_ms":{"type":"integer","format":"int32"},"status_code":{"type":"integer","format":"int32"},"url":{"type":"string"}}},"CronInfo":{"type":"object","required":["id","project_id","environment_id","path","schedule","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"deleted_at":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"next_run":{"type":["string","null"]},"path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"schedule":{"type":"string"},"updated_at":{"type":"string"}}},"CrossProjectSiblingRef":{"type":"object","description":"A sibling project that shares the same `trace_id`, returned by the\nPhase 1 cross-project banner endpoint.","required":["project_id","project_name","project_slug","first_seen"],"properties":{"first_seen":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC, `Z` suffix) of first span ingest for this\n`(trace_id, project_id)` pair."},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the sibling project's single-project trace view."}}},"CrossProjectTraceResponse":{"type":"object","description":"Response body for `GET /otel/traces/cross-project/{trace_id}`.\n\nAn empty `siblings` vec is the normal single-project case — never 404.","required":["trace_id","siblings"],"properties":{"siblings":{"type":"array","items":{"$ref":"#/components/schemas/CrossProjectSiblingRef"},"description":"Projects other than the caller's that hold spans for this trace,\nordered by `first_seen ASC`."},"trace_id":{"type":"string","description":"The trace_id that was queried (echoed back for client convenience)."}}},"CurrentStatusResponse":{"type":"object","required":["monitor_id","current_status","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["number","null"],"format":"double"},"current_status":{"type":"string"},"last_check_at":{"type":["string","null"],"format":"date-time"},"monitor_id":{"type":"integer","format":"int32"},"uptime_percentage":{"type":"number","format":"double"}}},"CustomDomainRequest":{"type":"object","required":["domain","environment_id"],"properties":{"branch":{"type":["string","null"]},"domain":{"type":"string"},"environment_id":{"type":"integer","format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to (only for docker-compose projects)"},"status_code":{"type":["integer","null"],"format":"int32"}}},"CustomDomainResponse":{"type":"object","required":["id","project_id","domain","status","created_at","updated_at"],"properties":{"branch":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"domain_id":{"type":["integer","null"],"format":"int32"},"environment":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DomainEnvironmentResponse"}]},"expiration_time":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"last_renewed":{"type":["integer","null"],"format":"int64"},"message":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to"},"status":{"type":"string"},"status_code":{"type":["integer","null"],"format":"int32"},"updated_at":{"type":"integer","format":"int64"}}},"CustomerMovementResponse":{"type":"object","required":["bucket","new_customers","churned_customers"],"properties":{"bucket":{"type":"string","format":"date-time"},"churned_customers":{"type":"integer","format":"int64"},"new_customers":{"type":"integer","format":"int64"}}},"DashboardLayout":{"type":"object","description":"The typed layout persisted (as JSONB) in `metric_dashboards.layout`.","required":["sections"],"properties":{"sections":{"type":"array","items":{"$ref":"#/components/schemas/DashboardSection"},"description":"Ordered sections that make up the dashboard."}}},"DashboardProjectsAnalyticsQuery":{"type":"object","description":"Query parameters for batch dashboard analytics","required":["project_ids","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"project_ids":{"type":"string","description":"Comma-separated list of project IDs"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"DashboardProjectsAnalyticsResponse":{"type":"object","description":"Batch response for dashboard project analytics","required":["projects"],"properties":{"projects":{"type":"object","description":"Map of project_id -> analytics data","additionalProperties":{"$ref":"#/components/schemas/ProjectDashboardAnalytics"},"propertyNames":{"type":"string"}}}},"DashboardSection":{"type":"object","description":"A titled group of tiles within a dashboard.","required":["id","title","tiles"],"properties":{"id":{"type":"string","description":"Stable client-generated section id."},"tiles":{"type":"array","items":{"$ref":"#/components/schemas/DashboardTile"},"description":"Tiles rendered within this section."},"title":{"type":"string","description":"Section heading."}}},"DashboardTile":{"type":"object","description":"A single metric tile within a dashboard section.","required":["id","metric_name","aggregation"],"properties":{"aggregation":{"type":"string","description":"Aggregation applied per bucket: one of\n`avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys to break the metric down by (group-by / multi-series view).\nEmpty = single aggregated series (current behavior). Max 2 keys — more\ndimensions are unreadable in a chart (ADR-026 Phase 2). Each key must\nmatch `[a-zA-Z0-9_.:-]`. Wired directly to `MetricQuery.group_by` by\nthe tile query path (separate frontend task)."},"id":{"type":"string","description":"Stable client-generated tile id (used as a React key / for reordering)."},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters: `[[\"key\",\"value\"],…]`. Empty = no\nfiltering. Max 10 pairs; keys must match `[a-zA-Z0-9_.:-]`; values\ncapped at 500 characters. Not yet wired into the tile query path\n(Phase 1 ADR-026 — field round-trips and validates; query wiring is\na separate frontend task)."},"metric_name":{"type":"string","description":"The metric name to chart (e.g. `http.server.duration`)."},"title":{"type":["string","null"],"description":"Optional display title; falls back to the metric name in the UI."}}},"DataImplication":{"type":"object","description":"A specific data implication the user needs to understand","required":["severity","message"],"properties":{"message":{"type":"string","description":"Human-readable description of what could happen"},"recommended_action":{"type":["string","null"],"description":"What the user should do about it (if anything)"},"severity":{"$ref":"#/components/schemas/DataImplicationSeverity","description":"Severity of this implication"}}},"DataImplicationSeverity":{"type":"string","description":"Severity of a data implication","enum":["info","warning","data-not-migrated","potential-data-loss"]},"DatabaseMetricsResponse":{"type":"object","description":"Response for the per-database metrics breakdown.","required":["databases"],"properties":{"databases":{"type":"array","items":{"$ref":"#/components/schemas/DatabaseMetricsRow"},"description":"One entry per database, sorted by the first metric descending\n(largest first) so the biggest database leads the table."}}},"DatabaseMetricsRow":{"type":"object","description":"Per-database metric values for a Postgres service.\n\nA Postgres instance can host many databases (some unrelated to this\nservice). The collector records per-`datname` series; this groups the\nlatest value of each requested metric by database so the UI can render a\n\"Databases\" breakdown table instead of one collapsed number.","required":["database","metrics"],"properties":{"database":{"type":"string","description":"Database name (`datname`)."},"metrics":{"type":"object","description":"Latest value of each requested metric for this database\n(e.g. `{\"pg.database_size_bytes\": 7943871, \"pg.cache_hit_ratio\": 0.99}`).","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}},"DelRequest":{"type":"object","description":"Request to delete keys","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"},"description":"The key(s) to delete","example":["user:123","user:456"]},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"DelResponse":{"type":"object","description":"Response for delete operation","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","description":"Number of keys deleted","example":2}}},"DeleteBlobRequest":{"type":"object","description":"Request to delete blobs","required":["pathnames"],"properties":{"pathnames":{"type":"array","items":{"type":"string"},"description":"Pathnames to delete (relative to project)","example":["images/avatar.png","documents/file.pdf"]},"projectId":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"DeleteBlobResponse":{"type":"object","description":"Response after deleting blobs","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","description":"Number of blobs deleted","example":2}}},"DeleteResponse":{"type":"object","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","minimum":0}}},"DeployFromImageRequest":{"type":"object","properties":{"external_image_id":{"type":["integer","null"],"format":"int32","description":"External image ID (if already registered). If provided without image_ref,\nthe image reference will be fetched from the registered external image."},"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nImage deploys can't read `.temps.yaml`, so this sets the path the deployer\nprobes after the container starts and the path the environment's uptime\nmonitor checks. Must start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"image_ref":{"type":["string","null"],"description":"Docker image reference (e.g., \"ghcr.io/org/app:v1.0\")\nRequired if external_image_id is not provided","example":"ghcr.io/myorg/myapp:v1.0"},"metadata":{"description":"Optional deployment metadata"}}},"DeployFromImageUploadQuery":{"type":"object","description":"Query parameters for deploying from an uploaded image tarball","properties":{"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nMust start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"tag":{"type":["string","null"],"description":"Tag to apply to the imported image (e.g., \"myapp:v1.0\")\nIf not provided, a unique tag will be generated","example":"myapp:v1.0"}}},"DeployFromStaticRequest":{"type":"object","required":["static_bundle_id"],"properties":{"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nStatic deploys can't read `.temps.yaml`, so this sets the path the deployer\nprobes after the container starts and the path the environment's uptime\nmonitor checks. Must start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"metadata":{"description":"Optional deployment metadata"},"static_bundle_id":{"type":"integer","format":"int32","description":"Static bundle ID (required)"}}},"DeploymentConfig":{"type":"object","description":"Deployment configuration shared between projects and environments\n\nThis configuration can be set at the project level (as defaults) and\noverridden at the environment level for specific deployments.\n\nNote: Environment variables are managed separately and are not part of this config.","properties":{"antiAffinity":{"type":"boolean","description":"Anti-affinity: spread replicas across different nodes.\n\nWhen enabled, the scheduler avoids placing two replicas of the same\nenvironment on the same node. If there are fewer eligible nodes than\nreplicas, remaining replicas wrap around (best-effort spreading).\n\nDefaults to `true` — replicas spread by default."},"automaticDeploy":{"type":["boolean","null"],"description":"Enable automatic deployments on git push.\n`None` = inherit from project config; `Some(true/false)` = explicit override.\nStored as JSONB so absent key → `None` (inherit), never silently defaults to false."},"containerExecEnabled":{"type":"boolean","description":"Enable container exec/shell access (disabled by default for security)"},"cpuLimit":{"type":["integer","null"],"format":"int32","description":"CPU limit in microcores, where 1_000_000 = 1 full CPU core\n(e.g., 2_000_000 = 2 CPUs). NOT millicores. `None` = uncapped."},"cpuRequest":{"type":["integer","null"],"format":"int32","description":"CPU request in microcores, where 1_000_000 = 1 full CPU core\n(e.g., 100_000 = 0.1 CPU, 500_000 = 0.5 CPU, 2_000_000 = 2 CPUs).\nNOT millicores — the deployer formats this as `{n}u` and converts\n`n / 1_000_000` cores into Docker nano_cpus."},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container\nIf not specified, will be auto-detected from Docker image or default to 3000"},"idleTimeoutSeconds":{"type":"integer","format":"int32","description":"Seconds of inactivity before containers are stopped in on-demand mode.\nOnly used when `on_demand` is true. Min: 60, Max: 86400 (24h).\nDefault: 300 (5 minutes)."},"memoryLimit":{"type":["integer","null"],"format":"int32","description":"Memory limit in megabytes. Three-state semantics:\n- `None` → inherit the parent layer (env inherits project, project\n inherits the seeded default); used by the settings UI's \"Use default\".\n- `Some(0)` → explicit **uncapped**: stop inheriting and run with no\n memory limit. This is the deliberate escape hatch for dedicated\n workloads, distinct from `None`.\n- `Some(n)` → hard cap of `n` MB.\n\n`merge`/resolution keep `Some(0)` as a present value (it wins precedence\nover a parent cap), and the deployer collapses it to \"no limit\" before\ntalking to Docker."},"memoryRequest":{"type":["integer","null"],"format":"int32","description":"Memory request in megabytes (e.g., 128 = 128MB)"},"onDemand":{"type":"boolean","description":"Enable on-demand mode (scale-to-zero).\nWhen enabled, containers are stopped after `idle_timeout_seconds` of no traffic\nand automatically started when a new request arrives."},"performanceMetricsEnabled":{"type":"boolean","description":"Enable performance metrics collection (speed insights)"},"replicas":{"type":"integer","format":"int32","description":"Number of replicas/instances to run\nDefaults to 1 replica"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig","description":"Security configuration (headers, rate limiting, attack mode, etc.)\nThese settings inherit and override from parent level (Environment > Project > Global)"}]},"sessionRecordingEnabled":{"type":"boolean","description":"Enable session recording for analytics"},"targetLabels":{"description":"Label selector for node-based scheduling. Replicas are only deployed to\nnodes whose labels match the selector.\n\nMatching rules:\n- **Same key, array value** → OR: node must match any value\n- **Different keys** → AND: node must satisfy all keys\n\nExample: `{\"region\": [\"us\", \"asia\"], \"gpu\": \"true\"}`\n→ (region=us OR region=asia) AND gpu=true\n\nApplied after `target_nodes` filtering (they stack)."},"targetNodes":{"type":["array","null"],"items":{"type":"integer","format":"int32"},"description":"Optional list of node IDs to deploy to. When set, replicas are distributed\nonly across these nodes (round-robin). When None, the scheduler distributes\nacross all active nodes (or deploys locally if no nodes exist)."},"wakeTimeoutSeconds":{"type":"integer","format":"int32","description":"Max seconds to wait for containers to start when waking from on-demand sleep.\nRequests return 503 if exceeded. Default: 30."}}},"DeploymentConfigSnapshot":{"type":"object","description":"Deployment configuration snapshot for deployments\n\nThis extends DeploymentConfig with environment variables to capture\nthe complete state of a deployment at the time it was created.","properties":{"automaticDeploy":{"type":"boolean","description":"Enable automatic deployments on git push"},"containerExecEnabled":{"type":"boolean","description":"Enable container exec/shell access"},"cpuLimit":{"type":["integer","null"],"format":"int32","description":"CPU limit in millicores"},"cpuRequest":{"type":["integer","null"],"format":"int32","description":"CPU request in millicores"},"environmentVariables":{"type":"object","description":"Environment variables used for this deployment","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container"},"memoryLimit":{"type":["integer","null"],"format":"int32","description":"Memory limit in megabytes"},"memoryRequest":{"type":["integer","null"],"format":"int32","description":"Memory request in megabytes"},"performanceMetricsEnabled":{"type":"boolean","description":"Enable performance metrics collection"},"replicas":{"type":"integer","format":"int32","description":"Number of replicas"},"sessionRecordingEnabled":{"type":"boolean","description":"Enable session recording"}}},"DeploymentConfiguration":{"type":"object","description":"Deployment-level configuration","required":["image","strategy","env_vars","ports","volumes","network","resources"],"properties":{"build":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/BuildConfiguration","description":"Build configuration (if building from source)"}]},"command":{"type":["array","null"],"items":{"type":"string"},"description":"Command override"},"entrypoint":{"type":["array","null"],"items":{"type":"string"},"description":"Entrypoint override"},"env_vars":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariable"},"description":"Environment variables"},"git":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GitSourcePlan","description":"Where the application's source code lives, when the source platform\nbuilds from a git repository. Execution uses this to link the temps\nproject to the same repository so the real deployment pipeline can\nclone and build it."}]},"health_check":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/HealthCheckConfiguration","description":"Health check configuration"}]},"image":{"type":"string","description":"Image to deploy"},"network":{"$ref":"#/components/schemas/NetworkConfiguration","description":"Network configuration"},"ports":{"type":"array","items":{"$ref":"#/components/schemas/PortMapping"},"description":"Port mappings"},"resources":{"$ref":"#/components/schemas/ResourceLimits","description":"Resource limits"},"strategy":{"$ref":"#/components/schemas/DeploymentStrategy","description":"Deployment strategy"},"volumes":{"type":"array","items":{"$ref":"#/components/schemas/VolumeMount"},"description":"Volume mounts"},"working_dir":{"type":["string","null"],"description":"Working directory"}}},"DeploymentContainerLogContentResponse":{"type":"object","description":"A single captured container-log dump, including its full text content.","required":["id","container_name","size_bytes","truncated","captured_at","content"],"properties":{"captured_at":{"type":"integer","format":"int64"},"container_name":{"type":"string"},"content":{"type":"string","description":"The captured plain-text log content."},"id":{"type":"integer","format":"int32"},"service_name":{"type":["string","null"]},"size_bytes":{"type":"integer","format":"int64"},"truncated":{"type":"boolean"}}},"DeploymentContainerLogResponse":{"type":"object","description":"Metadata for one captured (historical) container-log dump. Listed on the\ndeployment detail page so a user can pick which past container's logs to read.","required":["id","deployment_id","container_id","container_name","size_bytes","truncated","captured_at"],"properties":{"captured_at":{"type":"integer","format":"int64","description":"Unix epoch milliseconds of when the logs were captured (just before\nteardown). Matches the timestamp convention used by `DeploymentResponse`."},"container_id":{"type":"string"},"container_name":{"type":"string"},"deployment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"node_id":{"type":["integer","null"],"format":"int32"},"service_name":{"type":["string","null"]},"size_bytes":{"type":"integer","format":"int64"},"truncated":{"type":"boolean"}}},"DeploymentContainerLogsListResponse":{"type":"object","description":"The list of captured container-log dumps for a deployment.","required":["logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentContainerLogResponse"}}}},"DeploymentEnvironmentResponse":{"type":"object","required":["id","name","slug","domains"],"properties":{"domains":{"type":"array","items":{"type":"string"}},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"DeploymentJobResponse":{"type":"object","required":["id","deployment_id","job_id","job_type","name","status","created_at","updated_at","log_id"],"properties":{"created_at":{"type":"integer","format":"int64"},"dependencies":{},"deployment_id":{"type":"integer","format":"int32"},"description":{"type":["string","null"]},"error_message":{"type":["string","null"]},"execution_order":{"type":["integer","null"],"format":"int32"},"finished_at":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"job_config":{"description":"Internal workflow configuration is intentionally redacted. It can\ncontain legacy plaintext secrets or encrypted secret envelopes."},"job_id":{"type":"string"},"job_type":{"type":"string"},"log_id":{"type":"string"},"name":{"type":"string"},"outputs":{},"started_at":{"type":["integer","null"],"format":"int64"},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"DeploymentJobsResponse":{"type":"object","required":["jobs","total"],"properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentJobResponse"}},"total":{"type":"integer","minimum":0}}},"DeploymentListResponse":{"type":"object","required":["deployments","total","page","per_page"],"properties":{"deployments":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentResponse"}},"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"total":{"type":"integer","format":"int64"}}},"DeploymentMetadata":{"type":"object","description":"Deployment metadata - typed information about the deployment","properties":{"buildDurationMs":{"type":["integer","null"],"format":"int64","description":"Build duration in milliseconds"},"builder":{"type":["string","null"],"description":"Docker builder used (e.g., \"nixpacks\", \"dockerfile\")"},"deploymentDurationMs":{"type":["integer","null"],"format":"int64","description":"Deployment duration in milliseconds"},"deploymentSourceType":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SourceType","description":"Source type for THIS specific deployment (for Manual/flexible projects)\nThis allows Manual projects to have deployments via different methods\n(docker_image, static_files, or git) while keeping per-deployment tracking"}]},"dockerfilePath":{"type":["string","null"],"description":"Dockerfile path if using Dockerfile builder"},"externalImageId":{"type":["integer","null"],"format":"int32","description":"External image ID (reference to external_images table)"},"externalImageRef":{"type":["string","null"],"description":"External Docker image reference (for docker_image source type)\ne.g., \"ghcr.io/org/app:v1.0\" or \"docker.io/myapp:sha-abc123\""},"fileCount":{"type":["integer","null"],"format":"int32","description":"Number of files in the build output"},"gitPushEvent":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GitPushEvent","description":"Git push event that triggered this deployment (if from webhook)"}]},"healthCheckPath":{"type":["string","null"],"description":"Explicit deploy-time HTTP health-check path override.\nImage/static deploys can't read `.temps.yaml`, so this lets the deploy\nrequest set a custom path (e.g. \"/api/healthz\"). When present it takes\npriority over any `.temps.yaml` `health.path` value. Always starts with '/'."},"imageSizeBytes":{"type":["integer","null"],"format":"int64","description":"Total size of the built image in bytes"},"imageUploadedLocally":{"type":"boolean","description":"Whether the image was uploaded directly (via docker save/load) rather than pulled from registry\nWhen true, the PullExternalImageJob is skipped since the image is already loaded locally"},"isRollback":{"type":"boolean","description":"Whether this is a rollback deployment"},"labels":{"type":"array","items":{"type":"string"},"description":"Custom labels/tags for the deployment"},"rolledBackFromId":{"type":["integer","null"],"format":"int32","description":"ID of the deployment this was rolled back from (if applicable)"},"staticBundleContentType":{"type":["string","null"],"description":"Static bundle content type (for proper extraction: application/gzip or application/zip)"},"staticBundleId":{"type":["integer","null"],"format":"int32","description":"Static bundle ID (reference to static_bundles table, for static_files source type)"},"staticBundlePath":{"type":["string","null"],"description":"Static bundle path in blob storage (for static_files source type)"},"uploadedImageId":{"type":["string","null"],"description":"Docker image ID of the locally uploaded image (sha256:...)\nUsed to verify the image exists before deployment"}}},"DeploymentResponse":{"type":"object","required":["id","project_id","environment_id","environment","status","url","created_at","is_current"],"properties":{"branch":{"type":["string","null"]},"cancelled_reason":{"type":["string","null"]},"commit_author":{"type":["string","null"]},"commit_date":{"type":["integer","null"],"format":"int64"},"commit_hash":{"type":["string","null"]},"commit_message":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"deployment_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentConfigSnapshot","description":"Deployment configuration snapshot (CPU, memory, replicas, environment variables, etc.)"}]},"environment":{"$ref":"#/components/schemas/DeploymentEnvironmentResponse"},"environment_id":{"type":"integer","format":"int32"},"finished_at":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"is_current":{"type":"boolean"},"metadata":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentMetadata","description":"Deployment metadata (build info, git event, etc.)"}]},"project_id":{"type":"integer","format":"int32"},"screenshot_location":{"type":["string","null"]},"started_at":{"type":["integer","null"],"format":"int64"},"status":{"type":"string"},"tag":{"type":["string","null"]},"url":{"type":"string"}}},"DeploymentStateResponse":{"type":"object","required":["id","state","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"state":{"type":"string"}}},"DeploymentStrategy":{"type":"string","description":"Deployment strategy","enum":["replace","blue-green","rolling"]},"DeploymentTokenListResponse":{"type":"object","required":["tokens","total"],"properties":{"tokens":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentTokenResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"DeploymentTokenResponse":{"type":"object","required":["id","project_id","name","token_prefix","is_active","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"created_by":{"type":["integer","null"],"format":"int32"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"project_id":{"type":"integer","format":"int32"},"token_prefix":{"type":"string"}}},"DetectionConfig":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/StaticParams","description":"v0 (shipping): static threshold comparison of the aggregated value."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["static"]}}}],"description":"v0 (shipping): static threshold comparison of the aggregated value."},{"allOf":[{"$ref":"#/components/schemas/AnomalyParams","description":"Seasonal anomaly band (basic/agile/robust/ewma share this variant — the\nalgorithm is a field, not a new kind). Creation rejected until evaluated."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["anomaly"]}}}],"description":"Seasonal anomaly band (basic/agile/robust/ewma share this variant — the\nalgorithm is a field, not a new kind). Creation rejected until evaluated."},{"allOf":[{"$ref":"#/components/schemas/ForecastParams","description":"Predict a future threshold breach (capacity planning). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["forecast"]}}}],"description":"Predict a future threshold breach (capacity planning). Stub."},{"allOf":[{"$ref":"#/components/schemas/OutlierParams","description":"Cross-series population outlier (one host misbehaving vs its peers). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["outlier"]}}}],"description":"Cross-series population outlier (one host misbehaving vs its peers). Stub."},{"allOf":[{"$ref":"#/components/schemas/AutoWatchParams","description":"Watchdog-style self-tuning auto-watch (engine picks bounds). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["auto_watch"]}}}],"description":"Watchdog-style self-tuning auto-watch (engine picks bounds). Stub."}],"description":"The typed detector definition stored (as jsonb) in\n`metric_alert_rules.detection_config`.\n\nToday only [`DetectionConfig::Static`] is evaluable; the other variants are\nschema-present (so the SDK/UI and storage are already future-shaped) but\nrejected by [`DetectionConfig::validate`] until their evaluator lands. Each is\nthen enabled code-only, with no schema migration."},"DeviceCount":{"type":"object","required":["device_type","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"device_type":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"DigestSections":{"type":"object","description":"Sections that can be included in the weekly digest\nNote: `#[serde(default)]` allows backward compatibility when deserializing\nold data that may have `security` and `resources` fields instead of `projects`","properties":{"deployments":{"type":"boolean","default":true},"errors":{"type":"boolean","default":true},"funnels":{"type":"boolean","default":true},"performance":{"type":"boolean","default":true},"projects":{"type":"boolean","default":true}}},"Direction":{"type":"string","description":"Which side(s) of an anomaly band count as a deviation.","enum":["both","above","below"]},"DisableBlobResponse":{"type":"object","description":"Response after disabling Blob service","required":["success","message"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service disabled successfully"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"DisableKvResponse":{"type":"object","description":"Response after disabling KV service","required":["success","message"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service disabled successfully"},"success":{"type":"boolean","description":"Whether the service was successfully disabled"}}},"DisableMfaRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"DiscoverRequest":{"type":"object","description":"Request to discover workloads","required":["source"],"properties":{"credentials":{"$ref":"#/components/schemas/ImportCredentials","description":"Platform credentials (required for cloud platforms like Vercel, Railway)"},"selector":{"$ref":"#/components/schemas/ImportSelector","description":"Optional selector to filter workloads"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source to discover from"}}},"DiscoverResponse":{"type":"object","description":"Response with discovered workloads","required":["workloads"],"properties":{"workloads":{"type":"array","items":{"$ref":"#/components/schemas/WorkloadDescriptor"},"description":"Discovered workloads"}}},"DiskInfo":{"type":"object","description":"Disk space information for a single disk/partition","required":["mount_point","total_bytes","used_bytes","available_bytes","usage_percent","file_system"],"properties":{"available_bytes":{"type":"integer","format":"int64","description":"Available space in bytes","minimum":0},"file_system":{"type":"string","description":"File system type (e.g., \"ext4\", \"apfs\")"},"mount_point":{"type":"string","description":"Mount point of the disk"},"total_bytes":{"type":"integer","format":"int64","description":"Total space in bytes","minimum":0},"usage_percent":{"type":"number","format":"double","description":"Usage percentage (0-100)"},"used_bytes":{"type":"integer","format":"int64","description":"Used space in bytes","minimum":0}}},"DiskSpaceAlert":{"type":"object","description":"Alert for a disk that exceeds the threshold","required":["mount_point","usage_percent","threshold_percent","available_bytes","available_human"],"properties":{"available_bytes":{"type":"integer","format":"int64","description":"Available space in bytes","minimum":0},"available_human":{"type":"string","description":"Human-readable available space"},"mount_point":{"type":"string","description":"Mount point of the disk"},"threshold_percent":{"type":"integer","format":"int32","description":"Configured threshold percentage","minimum":0},"usage_percent":{"type":"number","format":"double","description":"Current usage percentage"}}},"DiskSpaceAlertSettings":{"type":"object","description":"Disk space alert settings for monitoring disk usage","properties":{"check_interval_seconds":{"type":"integer","format":"int64","description":"Interval in seconds between disk space checks","default":300,"example":300,"minimum":60},"enabled":{"type":"boolean","description":"Whether disk space alerts are enabled","default":true},"monitor_path":{"type":["string","null"],"description":"Restrict monitoring to the disk backing this path. When unset (the\ndefault), every mounted writable volume is monitored — including\ndedicated volumes such as `/var/lib/docker`.","default":null},"threshold_percent":{"type":"integer","format":"int32","description":"Threshold percentage (0-100) at which to trigger alerts","default":80,"example":80,"maximum":100,"minimum":0}}},"DiskSpaceCheckResult":{"type":"object","description":"Result of a disk space check","required":["checked_at","enabled","threshold_percent","disks","alerts"],"properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/DiskSpaceAlert"},"description":"Disks that meet or exceed the threshold"},"checked_at":{"type":"string","format":"date-time","description":"Timestamp of the check (ISO 8601, UTC)","example":"2026-05-28T12:15:47.609192Z"},"disks":{"type":"array","items":{"$ref":"#/components/schemas/DiskInfo"},"description":"List of all monitored disks"},"enabled":{"type":"boolean","description":"Whether disk space monitoring is enabled in settings"},"threshold_percent":{"type":"integer","format":"int32","description":"Configured alert threshold percentage (0-100)","minimum":0}}},"DnsAckRequest":{"type":"object","required":["applied_generation"],"properties":{"applied_generation":{"type":"integer","format":"int64","description":"Highest generation the agent has actually applied locally."}}},"DnsAckResponse":{"type":"object","required":["node_id","applied_generation","server_generation"],"properties":{"applied_generation":{"type":"integer","format":"int64"},"node_id":{"type":"integer","format":"int32"},"server_generation":{"type":"integer","format":"int64"}}},"DnsChallengeRecordResult":{"type":"object","description":"Result of a single DNS TXT record creation for ACME challenge","required":["name","value","success","message"],"properties":{"message":{"type":"string","description":"Human-readable message about the operation"},"name":{"type":"string","description":"TXT record name (e.g., \"_acme-challenge.example.com\")","example":"_acme-challenge.example.com"},"success":{"type":"boolean","description":"Whether the record was created successfully"},"value":{"type":"string","description":"TXT record value (the ACME challenge token)","example":"abc123..."}}},"DnsChangesResponse":{"type":"object","required":["generation","full_snapshot","records","removed_ids"],"properties":{"full_snapshot":{"type":"boolean","description":"`true` ⇒ replace the local zone with `records`. `false` ⇒ merge\n`records` into the existing zone (and remove `removed_ids`)."},"generation":{"type":"integer","format":"int64","description":"Highest generation included in this response. Agent ACKs this back."},"records":{"type":"array","items":{"$ref":"#/components/schemas/EndpointDto"}},"removed_ids":{"type":"array","items":{"type":"integer","format":"int64"},"description":"IDs the agent should remove from its zone. Always empty in the v1\nprotocol — the resolver reconciles by name on snapshot mode. Kept\nin the wire format so a future tombstone-based protocol doesn't\nrequire a breaking change."}}},"DnsCompletionResponse":{"type":"object","required":["domain","status"],"properties":{"domain":{"type":"string"},"status":{"type":"string"}}},"DnsLookupError":{"type":"object","description":"Error response for DNS lookup failures","required":["error","domain"],"properties":{"domain":{"type":"string","description":"Domain name that failed","example":"nonexistent.com"},"error":{"type":"string","description":"Error message","example":"DNS lookup failed: domain not found"}}},"DnsLookupRequest":{"type":"object","description":"Request to lookup DNS A records for a domain","required":["domain"],"properties":{"domain":{"type":"string","description":"Domain name to lookup","example":"example.com"}}},"DnsLookupResponse":{"type":"object","description":"Response containing DNS A records","required":["domain","records","count","dns_servers"],"properties":{"count":{"type":"integer","description":"Number of records found","example":1,"minimum":0},"dns_servers":{"type":"array","items":{"type":"string"},"description":"DNS servers used for the lookup","example":["8.8.8.8","8.8.4.4"]},"domain":{"type":"string","description":"Domain name that was queried","example":"example.com"},"records":{"type":"array","items":{"type":"string"},"description":"List of A record IP addresses","example":["93.184.216.34"]}}},"DnsProviderCredentials":{"oneOf":[{"type":"object","required":["api_token","type"],"properties":{"account_id":{"type":["string","null"]},"api_token":{"type":"string","example":"your-api-token"},"type":{"type":"string","enum":["cloudflare"]}}},{"type":"object","required":["api_user","api_key","type"],"properties":{"api_key":{"type":"string","example":"your-api-key"},"api_user":{"type":"string","example":"your-username"},"client_ip":{"type":["string","null"]},"sandbox":{"type":"boolean"},"type":{"type":"string","enum":["namecheap"]}}},{"type":"object","required":["access_key_id","secret_access_key","type"],"properties":{"access_key_id":{"type":"string","example":"AKIAIOSFODNN7EXAMPLE"},"region":{"type":["string","null"],"example":"us-east-1"},"secret_access_key":{"type":"string","example":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"},"session_token":{"type":["string","null"]},"type":{"type":"string","enum":["route53"]}}},{"type":"object","required":["api_token","type"],"properties":{"api_token":{"type":"string","example":"dop_v1_your-token"},"type":{"type":"string","enum":["digitalocean"]}}},{"type":"object","required":["service_account_email","private_key","project_id","type"],"properties":{"private_key":{"type":"string","example":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"},"project_id":{"type":"string","example":"my-gcp-project"},"service_account_email":{"type":"string","example":"dns-admin@myproject.iam.gserviceaccount.com"},"type":{"type":"string","enum":["gcp"]}}},{"type":"object","required":["tenant_id","client_id","client_secret","subscription_id","resource_group","type"],"properties":{"client_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"client_secret":{"type":"string"},"resource_group":{"type":"string","example":"my-resource-group"},"subscription_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"tenant_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"type":{"type":"string","enum":["azure"]}}},{"type":"object","description":"Pebble challtestsrv mock DNS (LOCAL DEV/TEST ONLY)","required":["management_url","type"],"properties":{"management_url":{"type":"string","example":"http://localhost:8055"},"type":{"type":"string","enum":["pebble"]}}}],"description":"DNS provider credentials (API-facing)"},"DnsProviderResponse":{"type":"object","description":"DNS provider response","required":["id","name","provider_type","credentials","is_active","flat_hostnames_supported","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"credentials":{"description":"Masked credentials for display"},"description":{"type":["string","null"]},"flat_hostnames_supported":{"type":"boolean","description":"Whether this provider benefits from the flat hostname mode (e.g. Cloudflare\nUniversal SSL). The UI surfaces/recommends the Flat toggle when true."},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_error":{"type":["string","null"]},"last_used_at":{"type":["string","null"]},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"string"}}},"DnsProviderSettings":{"type":"object","properties":{"cloudflare_api_key":{"type":["string","null"],"default":null},"provider":{"type":"string","default":"manual"}}},"DnsProviderSettingsMasked":{"type":"object","description":"DNS provider settings with masked sensitive fields","required":["provider"],"properties":{"cloudflare_api_key":{"type":["string","null"]},"provider":{"type":"string"}}},"DnsProviderType":{"type":"string","description":"Supported DNS provider types","enum":["cloudflare","namecheap","route53","digitalocean","gcp","azure","manual","pebble"]},"DnsRecord":{"type":"object","description":"A DNS record","required":["zone","name","fqdn","content","ttl"],"properties":{"content":{"$ref":"#/components/schemas/DnsRecordContent","description":"Record content"},"fqdn":{"type":"string","description":"Fully qualified domain name","example":"www.example.com"},"id":{"type":["string","null"],"description":"Provider-specific record ID (if exists)","example":"abc123"},"metadata":{"type":"object","description":"Provider-specific metadata","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Record name (without zone, e.g., \"www\" or \"@\" for root)","example":"www"},"proxied":{"type":"boolean","description":"Whether this record is proxied (Cloudflare-specific)"},"ttl":{"type":"integer","format":"int32","description":"Time to live in seconds","example":300,"minimum":0},"zone":{"type":"string","description":"Zone/domain this record belongs to","example":"example.com"}}},"DnsRecordChange":{"type":"object","description":"A single DNS record change the Cloudflare sync would make.","required":["action","name","record_type","value"],"properties":{"action":{"type":"string","description":"`\"create\"`, `\"update\"`, or `\"delete\"`."},"name":{"type":"string"},"record_type":{"type":"string","description":"Record type, e.g. `\"A\"` or `\"CNAME\"`."},"value":{"type":"string"}}},"DnsRecordContent":{"oneOf":[{"type":"object","description":"A record - IPv4 address (as string, e.g., \"192.0.2.1\")","required":["value","type"],"properties":{"type":{"type":"string","enum":["A"]},"value":{"type":"object","description":"A record - IPv4 address (as string, e.g., \"192.0.2.1\")","required":["address"],"properties":{"address":{"type":"string","example":"192.0.2.1"}}}}},{"type":"object","description":"AAAA record - IPv6 address (as string, e.g., \"2001:db8::1\")","required":["value","type"],"properties":{"type":{"type":"string","enum":["AAAA"]},"value":{"type":"object","description":"AAAA record - IPv6 address (as string, e.g., \"2001:db8::1\")","required":["address"],"properties":{"address":{"type":"string","example":"2001:db8::1"}}}}},{"type":"object","description":"CNAME record - canonical name","required":["value","type"],"properties":{"type":{"type":"string","enum":["CNAME"]},"value":{"type":"object","description":"CNAME record - canonical name","required":["target"],"properties":{"target":{"type":"string"}}}}},{"type":"object","description":"TXT record - text content","required":["value","type"],"properties":{"type":{"type":"string","enum":["TXT"]},"value":{"type":"object","description":"TXT record - text content","required":["content"],"properties":{"content":{"type":"string"}}}}},{"type":"object","description":"MX record - mail exchange","required":["value","type"],"properties":{"type":{"type":"string","enum":["MX"]},"value":{"type":"object","description":"MX record - mail exchange","required":["priority","target"],"properties":{"priority":{"type":"integer","format":"int32","minimum":0},"target":{"type":"string"}}}}},{"type":"object","description":"NS record - nameserver","required":["value","type"],"properties":{"type":{"type":"string","enum":["NS"]},"value":{"type":"object","description":"NS record - nameserver","required":["nameserver"],"properties":{"nameserver":{"type":"string"}}}}},{"type":"object","description":"SRV record - service","required":["value","type"],"properties":{"type":{"type":"string","enum":["SRV"]},"value":{"type":"object","description":"SRV record - service","required":["priority","weight","port","target"],"properties":{"port":{"type":"integer","format":"int32","minimum":0},"priority":{"type":"integer","format":"int32","minimum":0},"target":{"type":"string"},"weight":{"type":"integer","format":"int32","minimum":0}}}}},{"type":"object","description":"CAA record - certification authority authorization","required":["value","type"],"properties":{"type":{"type":"string","enum":["CAA"]},"value":{"type":"object","description":"CAA record - certification authority authorization","required":["flags","tag","value"],"properties":{"flags":{"type":"integer","format":"int32","minimum":0},"tag":{"type":"string"},"value":{"type":"string"}}}}},{"type":"object","description":"PTR record - pointer","required":["value","type"],"properties":{"type":{"type":"string","enum":["PTR"]},"value":{"type":"object","description":"PTR record - pointer","required":["target"],"properties":{"target":{"type":"string"}}}}}],"description":"DNS record content - varies by record type"},"DnsRecordResponse":{"type":"object","required":["record_type","name","value","status"],"properties":{"name":{"type":"string","description":"DNS record name (host)","example":"temps._domainkey.example.com"},"priority":{"type":["integer","null"],"format":"int32","description":"Priority (for MX records)","example":"10","minimum":0},"record_type":{"type":"string","description":"Record type: TXT, CNAME, MX","example":"TXT"},"status":{"$ref":"#/components/schemas/DnsRecordStatusResponse","description":"Verification status: unknown, verified, pending, failed"},"value":{"type":"string","description":"DNS record value","example":"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3..."}}},"DnsRecordSetupResult":{"type":"object","description":"Result of a single DNS record creation","required":["record_type","name","success","automatic","message"],"properties":{"automatic":{"type":"boolean","description":"Whether the operation was automatic or manual"},"message":{"type":"string","description":"Human-readable message"},"name":{"type":"string","description":"Record name"},"record_type":{"type":"string","description":"Record type (TXT, CNAME, MX)"},"success":{"type":"boolean","description":"Whether the record was created successfully"}}},"DnsRecordStatusResponse":{"type":"string","description":"DNS record verification status","enum":["unknown","verified","pending","failed"]},"DnsZone":{"type":"object","description":"A DNS zone (domain managed by the provider)","required":["id","name","status","nameservers"],"properties":{"id":{"type":"string","description":"Provider-specific zone ID","example":"zone123"},"metadata":{"type":"object","description":"Provider-specific metadata","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Zone name (domain)","example":"example.com"},"nameservers":{"type":"array","items":{"type":"string"},"description":"Nameservers for this zone"},"status":{"type":"string","description":"Zone status","example":"active"}}},"DockerComposePresetConfig":{"type":"object","description":"Configuration for Docker Compose deployments.","properties":{"composeOverride":{"type":["string","null"],"description":"User-provided docker-compose.override.yml content."},"composePath":{"type":["string","null"],"description":"Path to the Compose file relative to the project directory."},"publicPorts":{"type":"array","items":{"$ref":"#/components/schemas/ComposePublicPort"},"description":"Compose service ports that should be publicly routed."}}},"DockerRegistrySettings":{"type":"object","properties":{"ca_certificate":{"type":["string","null"],"default":null},"enabled":{"type":"boolean","default":false},"password":{"type":["string","null"],"default":null},"registry_url":{"type":["string","null"],"default":null},"tls_verify":{"type":"boolean","default":true},"username":{"type":["string","null"],"default":null}}},"DockerRegistrySettingsMasked":{"type":"object","description":"Docker registry settings with masked sensitive fields","required":["enabled","tls_verify"],"properties":{"ca_certificate":{"type":["string","null"]},"enabled":{"type":"boolean"},"password":{"type":["string","null"]},"registry_url":{"type":["string","null"]},"tls_verify":{"type":"boolean"},"username":{"type":["string","null"]}}},"DockerfilePresetConfig":{"type":"object","description":"Configuration for Dockerfile preset\nAllows customizing the Dockerfile path and build context for Docker-based deployments","properties":{"buildContext":{"type":["string","null"],"description":"Custom build context path (relative to repository root)\nIf not specified, uses the project's directory setting","example":"./api"},"dockerfilePath":{"type":["string","null"],"description":"Custom Dockerfile path (relative to build context)\nIf not specified, defaults to \"Dockerfile\" in the build context","example":"docker/Dockerfile"},"variant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DockerfileVariant","description":"Catalog variant. Normally omitted; `custom` selects the generated\nDockerfile compatibility preset."}]}}},"DockerfileVariant":{"type":"string","description":"Catalog variant persisted under the canonical Dockerfile preset.\n\nExisting rows predate this discriminator and therefore deserialize as\n[`DockerfileVariant::File`].","enum":["file","custom"]},"DomainAction":{"type":"string","description":"What to do with a domain during migration","enum":["import","skip"]},"DomainChallengeResponse":{"type":"object","required":["domain","txt_records","status"],"properties":{"domain":{"type":"string"},"status":{"type":"string"},"txt_records":{"type":"array","items":{"$ref":"#/components/schemas/TxtRecord"},"description":"Array of TXT records to add to DNS. For wildcards, multiple records are required."}}},"DomainEnvironmentResponse":{"type":"object","required":["id","name","slug"],"properties":{"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"DomainError":{"type":"object","required":["message","code"],"properties":{"code":{"type":"string"},"details":{"type":["string","null"]},"message":{"type":"string"}}},"DomainPlan":{"type":"object","description":"Plan for migrating a single custom domain","required":["domain","environment","action","action_description"],"properties":{"action":{"$ref":"#/components/schemas/DomainAction","description":"What to do with this domain"},"action_description":{"type":"string","description":"Human-readable explanation"},"domain":{"type":"string","description":"Full domain name"},"environment":{"type":"string","description":"Which environment to associate with (\"production\")"},"redirect_to":{"type":["string","null"],"description":"Redirect target (if this is a redirect domain)"},"replacement":{"type":["string","null"],"description":"The temps-side address that replaces this domain when it is skipped.\n\nSource-generated domains (sslip.io / traefik.me / platform subdomains)\nembed the source server's IP and would keep pointing at the old\nmachine — this tells the user where the app will be reachable on\ntemps instead."},"status_code":{"type":["integer","null"],"format":"int32","description":"Redirect status code"}}},"DomainResponse":{"type":"object","required":["id","domain","status","is_wildcard","verification_method","created_at","updated_at"],"properties":{"certificate":{"type":["string","null"],"description":"The PEM-encoded certificate chain (can be displayed in browser or downloaded)"},"created_at":{"type":"integer","format":"int64"},"dns_challenge_token":{"type":["string","null"]},"dns_challenge_value":{"type":["string","null"]},"domain":{"type":"string"},"expiration_time":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"is_wildcard":{"type":"boolean"},"last_error":{"type":["string","null"]},"last_error_type":{"type":["string","null"]},"last_renewed":{"type":["integer","null"],"format":"int64"},"on_demand_backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand TLS negative-cache deadline (epoch millis), when this hostname's\non-demand HTTP-01 issuance is in backoff after a failure (ADR-018 §4).\n`None` means no active backoff."},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"},"verification_method":{"type":"string"}}},"DrainNodeResponse":{"type":"object","required":["id","name","status","affected_environments","message"],"properties":{"affected_environments":{"type":"integer","minimum":0},"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"DrainStatusResponse":{"type":"object","description":"Progress of a node drain operation.","required":["node_id","node_name","status","remaining_containers","drain_complete","can_remove","message"],"properties":{"can_remove":{"type":"boolean","description":"Can the node be safely removed?"},"drain_complete":{"type":"boolean","description":"Whether the drain is complete (all containers migrated)"},"message":{"type":"string"},"node_id":{"type":"integer","format":"int32"},"node_name":{"type":"string"},"remaining_containers":{"type":"integer","description":"Number of containers still on this node","minimum":0},"status":{"type":"string"}}},"DropOffPoint":{"type":"object","description":"Drop-off point: pages where visitors leave the site","required":["page_path","exit_count","total_views","exit_rate"],"properties":{"exit_count":{"type":"integer","format":"int64","description":"Number of exits from this page"},"exit_rate":{"type":"number","format":"double","description":"Exit rate for this page (exit_count / total_views)"},"page_path":{"type":"string","description":"The page path where visitors drop off"},"total_views":{"type":"integer","format":"int64","description":"Total views of this page"}}},"EmailConfig":{"type":"object","required":["smtp_host","smtp_port","username","password","from_address","to_addresses"],"properties":{"accept_invalid_certs":{"type":"boolean"},"from_address":{"type":"string"},"from_name":{"type":["string","null"]},"password":{"type":"string"},"smtp_host":{"type":"string"},"smtp_port":{"type":"integer","format":"int32","minimum":0},"starttls_required":{"type":"boolean"},"tls_mode":{"$ref":"#/components/schemas/TlsMode"},"to_addresses":{"type":"array","items":{"type":"string"}},"username":{"type":"string"}}},"EmailDomainResponse":{"type":"object","required":["id","provider_id","domain","status","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"domain":{"type":"string","example":"updates.example.com"},"id":{"type":"integer","format":"int32"},"last_verified_at":{"type":["string","null"]},"provider_id":{"type":"integer","format":"int32"},"status":{"type":"string","example":"verified"},"updated_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"verification_error":{"type":["string","null"]}}},"EmailDomainWithDnsResponse":{"type":"object","required":["domain","dns_records"],"properties":{"dns_records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordResponse"}},"domain":{"$ref":"#/components/schemas/EmailDomainResponse"}}},"EmailProviderResponse":{"type":"object","required":["id","name","provider_type","region","is_active","credentials","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"credentials":{"description":"Masked credentials for display"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string","example":"My AWS SES"},"provider_type":{"$ref":"#/components/schemas/EmailProviderTypeRoute"},"region":{"type":"string","example":"us-east-1"},"sns_topic_arn":{"type":["string","null"]},"updated_at":{"type":"string","example":"2025-12-03T10:30:00Z"}}},"EmailProviderTypeRoute":{"type":"string","enum":["ses","scaleway","smtp"]},"EmailRequest":{"type":"object","description":"Request body carrying just an email address (password-reset request).","required":["email"],"properties":{"email":{"type":"string"}}},"EmailResponse":{"type":"object","required":["id","from_address","to_addresses","subject","status","created_at","track_opens","track_clicks","open_count","click_count"],"properties":{"bcc_addresses":{"type":["array","null"],"items":{"type":"string"}},"cc_addresses":{"type":["array","null"],"items":{"type":"string"}},"click_count":{"type":"integer","format":"int32","description":"Number of times links in the email were clicked"},"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"domain_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"first_clicked_at":{"type":["string","null"],"description":"When a link was first clicked"},"first_opened_at":{"type":["string","null"],"description":"When the email was first opened"},"from_address":{"type":"string","example":"hello@updates.example.com"},"from_name":{"type":["string","null"]},"headers":{"type":["object","null"],"additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"html_body":{"type":["string","null"]},"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"open_count":{"type":"integer","format":"int32","description":"Number of times the email was opened"},"project_id":{"type":["integer","null"],"format":"int32"},"provider_message_id":{"type":["string","null"]},"reply_to":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"status":{"type":"string","example":"sent"},"subject":{"type":"string"},"tags":{"type":["array","null"],"items":{"type":"string"}},"text_body":{"type":["string","null"]},"to_addresses":{"type":"array","items":{"type":"string"}},"track_clicks":{"type":"boolean","description":"Whether click tracking is enabled"},"track_opens":{"type":"boolean","description":"Whether open tracking is enabled"},"tracked_html_body":{"type":["string","null"],"description":"The final HTML sent to the provider (with tracking pixel and rewritten links)"}}},"EmailStatsResponse":{"type":"object","required":["total","sent","failed","queued","captured"],"properties":{"captured":{"type":"integer","format":"int64","description":"Emails captured without sending (Mailhog mode - no provider configured)","minimum":0},"failed":{"type":"integer","format":"int64","minimum":0},"queued":{"type":"integer","format":"int64","minimum":0},"sent":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"EmailStatusResponse":{"type":"object","required":["email_configured","password_reset_available","oidc_providers"],"properties":{"email_configured":{"type":"boolean"},"oidc_providers":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderSummary"}},"password_reset_available":{"type":"boolean"}}},"EmailTrackingResponse":{"type":"object","description":"Email tracking summary","required":["email_id","track_opens","track_clicks","open_count","click_count","unique_opens","unique_clicks","links"],"properties":{"click_count":{"type":"integer","format":"int32"},"email_id":{"type":"string"},"first_clicked_at":{"type":["string","null"]},"first_opened_at":{"type":["string","null"]},"links":{"type":"array","items":{"$ref":"#/components/schemas/TrackedLinkResponse"}},"open_count":{"type":"integer","format":"int32"},"track_clicks":{"type":"boolean"},"track_opens":{"type":"boolean"},"unique_clicks":{"type":"integer","format":"int64","minimum":0},"unique_opens":{"type":"integer","format":"int64","minimum":0}}},"EmailTrackingSetupResponse":{"type":"object","description":"Result of the one-click AWS-side event-tracking setup.","required":["topic_arn","webhook_url","subscription_requested","event_destination_attached"],"properties":{"event_destination_attached":{"type":"boolean","description":"The SESv2 event destination (bounce/complaint/delivery) is attached\nto the `temps-tracking` configuration set."},"subscription_requested":{"type":"boolean","description":"The webhook subscription was requested; SNS confirms it\nasynchronously through the webhook itself."},"topic_arn":{"type":"string","example":"arn:aws:sns:us-east-1:123456789012:temps-email-events-1"},"webhook_url":{"type":"string"}}},"EmailTrackingStatusResponse":{"type":"object","description":"Live status of the SES event-tracking pipeline for one provider.","required":["webhook_url","supports_event_tracking"],"properties":{"last_event_at":{"type":["string","null"],"description":"Most recent delivered/bounced/complained event recorded for an email\nsent through this provider. `null` means no provider feedback has\narrived yet.","example":"2026-07-18T10:31:00Z"},"sns_topic_arn":{"type":["string","null"]},"subscription_confirmed_at":{"type":["string","null"],"description":"When the SNS subscription for the current topic was confirmed.\n`null` with a topic set usually means the subscription is still\npending — most often because the endpoint was subscribed before the\ntopic ARN was saved here.","example":"2026-07-18T10:30:00Z"},"supports_event_tracking":{"type":"boolean","description":"Only SES providers support SNS event tracking."},"webhook_url":{"type":"string","description":"Public webhook endpoint SNS must deliver events to.","example":"https://temps.example.com/api/t/webhook/ses"}}},"EmbeddingData":{"type":"object","required":["object","embedding","index"],"properties":{"embedding":{"type":"array","items":{"type":"number","format":"double"}},"index":{"type":"integer","format":"int32"},"object":{"type":"string"}}},"EmbeddingInput":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"EmbeddingRequest":{"type":"object","required":["model","input"],"properties":{"dimensions":{"type":["integer","null"],"format":"int32"},"encoding_format":{"type":["string","null"]},"input":{"$ref":"#/components/schemas/EmbeddingInput"},"model":{"type":"string"}}},"EmbeddingResponse":{"type":"object","required":["object","data","model","usage"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmbeddingData"}},"model":{"type":"string"},"object":{"type":"string"},"usage":{"$ref":"#/components/schemas/EmbeddingUsage"}}},"EmbeddingUsage":{"type":"object","required":["prompt_tokens","total_tokens"],"properties":{"prompt_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"EnableBlobRequest":{"type":"object","description":"Request to enable Blob service","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (optional, defaults to RustFS)","example":"ghcr.io/rustfs/rustfs:0.5.0"},"root_password":{"type":["string","null"],"description":"Root password for S3 access"},"root_user":{"type":["string","null"],"description":"Root user for S3 access"}}},"EnableBlobResponse":{"type":"object","description":"Response after enabling Blob service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service enabled successfully"},"status":{"$ref":"#/components/schemas/BlobStatusResponse","description":"Current status"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"EnableKvRequest":{"type":"object","description":"Request to enable the KV service","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (optional, uses default if not provided)","example":"gotempsh/redis-walg:8-bookworm"},"max_memory":{"type":["string","null"],"description":"Maximum memory allocation (e.g., \"256mb\", \"1gb\")","example":"256mb"},"persistence":{"type":"boolean","description":"Enable data persistence"}}},"EnableKvResponse":{"type":"object","description":"Response after enabling KV service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service enabled successfully"},"status":{"$ref":"#/components/schemas/KvStatusResponse","description":"Current service status"},"success":{"type":"boolean","description":"Whether the service was successfully enabled"}}},"EnablePgStatStatementsResponse":{"type":"object","description":"Response for the enable pg_stat_statements endpoint.","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable message confirming the action."}}},"EndpointDto":{"type":"object","description":"One DNS record on the wire. Mirrors `service_endpoints::Model` but\nkeeps the API stable across entity evolution. `target_ip` is a string\n(v4 or v6 literal, or CNAME target hostname) parsed by the resolver.","required":["id","fqdn","record_type","ttl","owner_kind","owner_id","generation"],"properties":{"fqdn":{"type":"string"},"generation":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int64"},"node_id":{"type":["integer","null"],"format":"int32"},"owner_id":{"type":"integer","format":"int64"},"owner_kind":{"type":"string"},"record_type":{"type":"string"},"target_ip":{"type":["string","null"]},"target_port":{"type":["integer","null"],"format":"int32"},"ttl":{"type":"integer","format":"int32"}}},"EnqueuedJob":{"type":"object","description":"A single job that was successfully enqueued during a fan-out run.","required":["backup_id","job_id","engine"],"properties":{"backup_id":{"type":"integer","format":"int32","description":"FK to `backups.id` for this job."},"engine":{"type":"string","description":"Engine key (e.g. `\"control_plane\"`, `\"redis\"`, `\"postgres_pgdump\"`)."},"job_id":{"type":"integer","format":"int64","description":"FK to `backup_jobs.id` for this job."},"target_service_id":{"type":["integer","null"],"format":"int32","description":"FK to `external_services.id` when this is an external-service job.\n`None` for the control-plane job."}}},"EnrichVisitorRequest":{"type":"object","required":["custom_data"],"properties":{"custom_data":{"type":"object"}}},"EnrichVisitorResponse":{"type":"object","required":["success","visitor_id","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"},"visitor_id":{"type":"string"}}},"EnrollmentTokenInfo":{"type":"object","required":["id","expires_at","used_count","max_uses","created_at"],"properties":{"bound_node_name":{"type":["string","null"]},"created_at":{"type":"string"},"expires_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"max_uses":{"type":"integer","format":"int32"},"used_count":{"type":"integer","format":"int32"}}},"EnrollmentTokenListResponse":{"type":"object","required":["tokens"],"properties":{"tokens":{"type":"array","items":{"$ref":"#/components/schemas/EnrollmentTokenInfo"}}}},"EntityInfoResponse":{"type":"object","required":["container_path","entity","entity_type","fields"],"properties":{"container_path":{"type":"array","items":{"type":"string"},"description":"Full container path","example":["mydb","public"]},"entity":{"type":"string","description":"Entity name","example":"users"},"entity_type":{"type":"string","description":"Entity type","example":"table"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/FieldResponse"},"description":"Field definitions"},"metadata":{"description":"Additional metadata (content_type, last_modified, etag, etc.)"},"row_count":{"type":["integer","null"],"description":"Approximate row count (for tables/collections)","example":1234,"minimum":0},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes (for objects/files)","example":1048576,"minimum":0},"sort_schema":{"description":"JSON Schema for sort options (if supported)"}}},"EntityResponse":{"type":"object","required":["name","entity_type"],"properties":{"entity_type":{"type":"string","description":"Entity type (table, view, collection, etc.)","example":"table"},"name":{"type":"string","description":"Entity name (table/collection)","example":"users"},"row_count":{"type":["integer","null"],"description":"Approximate row count","example":1234,"minimum":0},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes (for files/objects)","example":1048576,"minimum":0}}},"EnvVarInput":{"type":"object","description":"Input for environment variable","required":["name","value"],"properties":{"name":{"type":"string","description":"Variable name"},"value":{"type":"string","description":"Variable value"}}},"EnvVarIntegrationInfo":{"type":"object","required":["service_id","service_name","service_type","service_updated_at"],"properties":{"service_id":{"type":"integer","format":"int32"},"service_name":{"type":"string"},"service_slug":{"type":["string","null"]},"service_type":{"type":"string"},"service_updated_at":{"type":"string"}}},"EnvVarResponse":{"type":"object","description":"Environment variable with masked sensitive values","required":["key","value","is_masked"],"properties":{"is_masked":{"type":"boolean","description":"Whether this is a sensitive/masked value"},"key":{"type":"string"},"value":{"type":"string"}}},"EnvVarTemplateResponse":{"type":"object","description":"Environment variable template response","required":["name","required"],"properties":{"default":{"type":["string","null"],"description":"Default value if not provided by user"},"default_generator":{"type":["string","null"],"description":"Frontend-side generator hint for the default value\n(e.g. `app_url`, `random_secret`, `random_hex_32`)"},"description":{"type":["string","null"],"description":"Description of what this variable is used for"},"example":{"type":["string","null"],"description":"Example value for documentation"},"name":{"type":"string","description":"Name of the environment variable"},"required":{"type":"boolean","description":"Whether this variable is required"}}},"EnvironmentConfiguration":{"type":"object","description":"Environment-level configuration","required":["name","subdomain","resources"],"properties":{"name":{"type":"string","description":"Environment name"},"resources":{"$ref":"#/components/schemas/ResourceLimits","description":"Resource limits for environment"},"subdomain":{"type":"string","description":"Proposed subdomain"}}},"EnvironmentDomainResponse":{"type":"object","required":["id","environment_id","domain","created_at","url"],"properties":{"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"url":{"type":"string","description":"Full URL for this domain (e.g., https://buildtolearndev-production.example.com)","example":"https://buildtolearndev-production.example.com"}}},"EnvironmentInfo":{"type":"object","required":["id","name","main_url"],"properties":{"current_deployment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"main_url":{"type":"string"},"name":{"type":"string"}}},"EnvironmentResponse":{"type":"object","required":["id","project_id","name","slug","main_url","subdomain","created_at","updated_at","is_preview","protected","sleeping"],"properties":{"attack_mode":{"type":["boolean","null"],"description":"Per-environment CAPTCHA attack-mode override.\n`null` means inherit the project-level `attack_mode`; `true`/`false`\nexplicitly enable/disable the challenge for this environment. Always\nserialized (NOT skipped) so the UI can distinguish `null` from `false`."},"branch":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"current_deployment_id":{"type":["integer","null"],"format":"int32"},"deployment_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentConfig","description":"Deployment configuration for this environment (overrides project-level config)"}]},"estimated_sleep_at":{"type":["integer","null"],"format":"int64","description":"Estimated time (epoch millis) when the environment will go to sleep\nbased on last activity + idle timeout. NULL when sleeping or on-demand disabled."},"force_https":{"type":["boolean","null"],"description":"Per-environment HTTP→HTTPS redirect override.\n`null` means inherit the proxy default (redirect only when the host has\nan active TLS certificate); `true` always redirects plain HTTP for this\nenvironment, `false` never does. Always serialized (NOT skipped) so the\nUI can distinguish `null` from `false`."},"id":{"type":"integer","format":"int32"},"is_preview":{"type":"boolean","description":"Indicates if this is a preview environment (auto-created per branch)\nFor preview environments, 'branch' contains the feature branch name"},"last_activity_at":{"type":["integer","null"],"format":"int64","description":"Last proxied request timestamp (epoch millis) for on-demand environments.\nNULL when on-demand is disabled or no traffic has been received yet."},"main_url":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"protected":{"type":"boolean","description":"When true, git pushes do NOT auto-deploy to this environment.\nDeployments must be promoted from another environment."},"sleeping":{"type":"boolean","description":"When true, the environment's containers are currently stopped due to\ninactivity (on-demand mode) and will start on the next request."},"slug":{"type":"string"},"subdomain":{"type":"string","description":"The host label stored for this environment (e.g.\n`myproject-production`). This is the prefix that is combined with the\nplatform's preview domain at request time to produce `main_url`. Edit\nthis via the rename-subdomain endpoint, not the full URL."},"updated_at":{"type":"integer","format":"int64"}}},"EnvironmentVariable":{"type":"object","description":"Environment variable","required":["key","value","is_secret"],"properties":{"is_secret":{"type":"boolean","description":"Whether this is a secret (should be encrypted)"},"key":{"type":"string","description":"Variable name"},"source_description":{"type":["string","null"],"description":"Where this env var originates from (for traceability)"},"value":{"type":"string","description":"Variable value (may be redacted for secrets)"}}},"EnvironmentVariableInfo":{"type":"object","required":["name","value","sensitive"],"properties":{"name":{"type":"string"},"sensitive":{"type":"boolean","description":"Whether this variable contains sensitive data (passwords, keys, tokens)","example":false},"value":{"type":"string"}}},"EnvironmentVariableResponse":{"type":"object","required":["id","key","created_at","updated_at","environments","include_in_preview","is_secret"],"properties":{"created_at":{"type":"integer","format":"int64"},"environments":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentInfo"}},"id":{"type":"integer","format":"int32"},"include_in_preview":{"type":"boolean","description":"Include this environment variable in preview environments"},"is_secret":{"type":"boolean","description":"Whether the variable is a write-only secret. Secrets always have\n`value: None` in responses."},"key":{"type":"string"},"updated_at":{"type":"integer","format":"int64"},"value":{"type":["string","null"],"description":"Plaintext value for non-secret vars (or `\"***\"` mask for list responses).\n`None` for secret vars — secrets are write-only."}}},"EnvironmentVariableValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"ErrorDashboardStatsQuery":{"type":"object","required":["start_time","end_time"],"properties":{"compare_to_previous":{"type":["boolean","null"]},"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"ErrorDashboardStatsResponse":{"type":"object","required":["total_errors","total_errors_previous_period","total_errors_change_percent","error_groups","error_groups_previous_period","start_time","end_time"],"properties":{"comparison_end_time":{"type":["string","null"],"format":"date-time"},"comparison_start_time":{"type":["string","null"],"format":"date-time"},"end_time":{"type":"string","format":"date-time"},"error_groups":{"type":"integer","format":"int64"},"error_groups_previous_period":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"total_errors":{"type":"integer","format":"int64"},"total_errors_change_percent":{"type":"number","format":"double"},"total_errors_previous_period":{"type":"integer","format":"int64"}}},"ErrorEventResponse":{"type":"object","required":["id","error_group_id","timestamp","created_at"],"properties":{"created_at":{"type":"string"},"data":{"description":"Full error event data (contains raw Sentry event or custom error data)"},"error_group_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int64"},"source":{"type":["string","null"],"description":"Source of the error event (e.g., \"sentry\", \"custom\", \"bugsnag\")"},"timestamp":{"type":"string"}}},"ErrorGroupResponse":{"type":"object","required":["id","title","error_type","first_seen","last_seen","total_count","status","project_id","created_at","updated_at"],"properties":{"assigned_to":{"type":["string","null"]},"created_at":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_type":{"type":"string"},"first_seen":{"type":"string"},"id":{"type":"integer","format":"int32"},"last_seen":{"type":"string"},"message_template":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"status":{"type":"string"},"title":{"type":"string"},"total_count":{"type":"integer","format":"int32"},"updated_at":{"type":"string"},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"ErrorGroupStatsResponse":{"type":"object","required":["total_groups","unresolved_groups","resolved_groups","ignored_groups"],"properties":{"ignored_groups":{"type":"integer","format":"int64"},"resolved_groups":{"type":"integer","format":"int64"},"total_groups":{"type":"integer","format":"int64"},"unresolved_groups":{"type":"integer","format":"int64"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"details":{"type":["string","null"]},"error":{"type":"string"}}},"ErrorRow":{"type":"object","required":["id","ts","error_group_id","fingerprint","error_class","stacktrace_preview","stacktrace_truncated"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_class":{"type":"string"},"error_group_id":{"type":"integer","format":"int32"},"fingerprint":{"type":"string"},"id":{"type":"integer","format":"int64"},"message":{"type":["string","null"]},"stacktrace_preview":{},"stacktrace_truncated":{"type":"boolean"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"ErrorTimeSeriesDataResponse":{"type":"object","required":["timestamp","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"ErrorTimeSeriesQuery":{"type":"object","required":["start_time","end_time"],"properties":{"bucket":{"type":"string","description":"Time bucket size (e.g., \"1h\", \"15m\", \"1d\", \"1 hour\", \"30 minutes\")","example":"1h"},"end_time":{"type":"string","format":"date-time"},"start_time":{"type":"string","format":"date-time"}}},"EventActivityBucket":{"type":"object","description":"Time bucket data point for event activity graph","required":["timestamp","count","unique_visitors"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences in this bucket"},"timestamp":{"type":"string","description":"Timestamp for this bucket (ISO 8601)"},"unique_visitors":{"type":"integer","format":"int64","description":"Number of unique visitors in this bucket"}}},"EventBreakdown":{"type":"string","enum":["country","region","city"]},"EventBrowserStats":{"type":"object","description":"Browser stats for an event","required":["browser","count","percentage"],"properties":{"browser":{"type":"string","description":"Browser name"},"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this browser"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"}}},"EventCount":{"type":"object","required":["event_name","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"event_name":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"EventCountryStats":{"type":"object","description":"Country stats for an event","required":["country","count","percentage"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this country"},"country":{"type":"string","description":"Country name"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"}}},"EventDetailQuery":{"type":"object","description":"Query parameters for event detail analytics","required":["event_name","project_id","start_date","end_date"],"properties":{"bucket_interval":{"type":["string","null"],"description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to get details for"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventDetailResponse":{"type":"object","description":"Summary response for a specific event's analytics","required":["event_name","total_count","unique_visitors","unique_sessions","activity_over_time","referrers","countries","browsers","bucket_interval"],"properties":{"activity_over_time":{"type":"array","items":{"$ref":"#/components/schemas/EventActivityBucket"},"description":"Time series data for event activity graph"},"browsers":{"type":"array","items":{"$ref":"#/components/schemas/EventBrowserStats"},"description":"Browser distribution of visitors who triggered this event"},"bucket_interval":{"type":"string","description":"Bucket interval used for time series ('hour', 'day', etc.)"},"countries":{"type":"array","items":{"$ref":"#/components/schemas/EventCountryStats"},"description":"Geographic distribution of visitors who triggered this event"},"event_name":{"type":"string","description":"The event name being analyzed"},"referrers":{"type":"array","items":{"$ref":"#/components/schemas/EventReferrerStats"},"description":"Top referrer hostnames for visitors who triggered this event"},"total_count":{"type":"integer","format":"int64","description":"Total number of times this event was triggered in the date range"},"unique_sessions":{"type":"integer","format":"int64","description":"Number of unique sessions where this event occurred"},"unique_visitors":{"type":"integer","format":"int64","description":"Number of unique visitors who triggered this event"}}},"EventEntriesQuery":{"type":"object","description":"Query parameters for the raw event entries list","required":["event_name","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to list occurrences for"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 20, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventEntriesResponse":{"type":"object","description":"Paginated response for raw event entries","required":["event_name","total_count","page","per_page","entries"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/EventEntryInfo"},"description":"Individual event occurrences, most recent first"},"event_name":{"type":"string","description":"The event name"},"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"total_count":{"type":"integer","format":"int64","description":"Total number of occurrences of this event in the date range"}}},"EventEntryInfo":{"type":"object","description":"A single raw occurrence of an event, including its custom JSON properties","required":["id","timestamp","page_path","href"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"City of the visitor at the time of the event"},"country":{"type":["string","null"],"description":"Country of the visitor at the time of the event"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"href":{"type":"string","description":"Full URL where the event was triggered"},"id":{"type":"integer","format":"int64","description":"Event row ID"},"page_path":{"type":"string","description":"Page path where the event was triggered"},"props":{"type":["object","null"],"description":"Custom event properties as JSON (null when the event carried no data)"},"session_id":{"type":["string","null"],"description":"Session ID the event belongs to (if any)"},"timestamp":{"type":"string","format":"date-time","description":"When the event occurred"},"visitor_id":{"type":["integer","null"],"format":"int32","description":"Visitor numeric ID (if known)"},"visitor_uuid":{"type":["string","null"],"description":"Visitor UUID (if known)"}}},"EventKind":{"type":"string","description":"Tag enum for filter parameters and routing. Matches the variant\ndiscriminator used by `ObservabilityEvent`.","enum":["request","span","error","revenue"]},"EventMetricsPayload":{"type":"object","required":["event_name","event_data","request_path","request_query"],"properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"event_data":{},"event_name":{"type":"string"},"fcp":{"type":["number","null"],"format":"float","description":"First Contentful Paint (milliseconds)"},"fid":{"type":["number","null"],"format":"float","description":"First Input Delay (milliseconds)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"},"language":{"type":["string","null"]},"lcp":{"type":["number","null"],"format":"float","description":"Largest Contentful Paint (milliseconds)"},"page_title":{"type":["string","null"]},"referrer":{"type":["string","null"],"description":"Referrer URL (falls back to Referer header if not provided)"},"request_path":{"type":"string"},"request_query":{"type":"string"},"screen_height":{"type":["integer","null"],"format":"int32","minimum":0},"screen_width":{"type":["integer","null"],"format":"int32","minimum":0},"ttfb":{"type":["number","null"],"format":"float","description":"Time to First Byte (milliseconds)"},"viewport_height":{"type":["integer","null"],"format":"int32","minimum":0},"viewport_width":{"type":["integer","null"],"format":"int32","minimum":0}}},"EventReferrerStats":{"type":"object","description":"Referrer stats for an event","required":["referrer","count","percentage"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this referrer"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"},"referrer":{"type":"string","description":"Referrer hostname or \"Direct\""}}},"EventTimeline":{"type":"object","required":["date","count"],"properties":{"count":{"type":"integer","format":"int64"},"date":{"type":"string","format":"date-time"}}},"EventTimelineQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"bucket_size":{"type":["string","null"],"description":"Bucket size: hour, day, or week (auto-detected if not specified)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":["string","null"]},"start_date":{"type":"string","format":"date-time"}}},"EventType":{"type":"object","required":["name","count"],"properties":{"count":{"type":"integer","format":"int64"},"name":{"type":"string"}}},"EventTypeBreakdown":{"type":"object","required":["event_type","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"event_type":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"EventTypeBreakdownQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventTypeResponse":{"type":"object","required":["event_type","description","category"],"properties":{"category":{"type":"string"},"description":{"type":"string"},"event_type":{"type":"string"}}},"EventTypesResponse":{"type":"object","required":["events","total","page","page_size"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"EventVisitorInfo":{"type":"object","description":"A visitor who triggered a specific event","required":["visitor_id","visitor_uuid","event_count","first_triggered","last_triggered"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"Visitor's city"},"country":{"type":["string","null"],"description":"Visitor's country"},"country_code":{"type":["string","null"],"description":"Visitor's country code"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"event_count":{"type":"integer","format":"int64","description":"Number of times this visitor triggered the event"},"first_triggered":{"type":"string","format":"date-time","description":"When the visitor first triggered the event in the date range"},"last_triggered":{"type":"string","format":"date-time","description":"When the visitor last triggered the event in the date range"},"referrer_hostname":{"type":["string","null"],"description":"Referrer hostname for the event"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor numeric ID"},"visitor_uuid":{"type":"string","description":"Visitor UUID"}}},"EventVisitorsQuery":{"type":"object","description":"Query parameters for event visitors list","required":["event_name","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to list visitors for"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 20, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventVisitorsResponse":{"type":"object","description":"Paginated response for event visitors","required":["event_name","total_count","page","per_page","visitors"],"properties":{"event_name":{"type":"string","description":"The event name"},"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"total_count":{"type":"integer","format":"int64","description":"Total number of unique visitors who triggered this event"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/EventVisitorInfo"},"description":"Individual visitors who triggered this event"}}},"EventsCountQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"custom_events_only":{"type":["boolean","null"],"description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventsResponse":{"type":"object","required":["events","applied_kinds"],"properties":{"applied_kinds":{"type":"array","items":{"$ref":"#/components/schemas/EventKind"},"description":"Echo of the kinds filter actually applied (server-resolved). Useful\nfor clients that pass `kinds=` empty and want to know what they got."},"events":{"type":"array","items":{"$ref":"#/components/schemas/ObservabilityEvent"}}}},"ExecBody":{"type":"object","required":["cmd"],"properties":{"cmd":{"type":"array","items":{"type":"string"}},"cwd":{"type":["string","null"]},"env":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}}},"additionalProperties":false},"ExecDetachedResponse":{"type":"object","required":["job_id"],"properties":{"job_id":{"type":"string"}}},"ExecResponse":{"type":"object","required":["exit_code","stdout","stderr"],"properties":{"exit_code":{"type":"integer","format":"int32"},"stderr":{"type":"string"},"stdout":{"type":"string"}}},"ExecuteImportRequest":{"type":"object","description":"Request to execute an import","required":["session_id","project_name","preset","directory","main_branch"],"properties":{"directory":{"type":"string","description":"Project directory","example":"."},"dry_run":{"type":["boolean","null"],"description":"Dry run mode (don't create resources)"},"main_branch":{"type":"string","description":"Main branch name","example":"main"},"preset":{"type":"string","description":"Preset to use for the project (e.g., \"nextjs\", \"express\", \"docker\")"},"project_name":{"type":"string","description":"Project name to use (overrides the name from the plan)","example":"my-app"},"session_id":{"type":"string","description":"Session ID from plan creation"}}},"ExecuteImportResponse":{"type":"object","description":"Response from import execution","required":["session_id","status","step_results"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Created deployment ID (if completed)"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Created environment ID (if completed)"},"project_id":{"type":["integer","null"],"format":"int32","description":"Created project ID (if completed)"},"session_id":{"type":"string","description":"Session ID"},"status":{"$ref":"#/components/schemas/ImportExecutionStatus","description":"Execution status"},"step_results":{"type":"array","items":{"$ref":"#/components/schemas/StepResult"},"description":"Per-step results (in execution order)"}}},"ExecuteOperationRequest":{"type":"object","required":["operation"],"properties":{"operation":{"type":"string"}}},"ExpireRequest":{"type":"object","description":"Request to set expiration on a key","required":["key","seconds"],"properties":{"key":{"type":"string","description":"The key to set expiration on","example":"session:abc"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"seconds":{"type":"integer","format":"int64","description":"Expiration time in seconds","example":3600}}},"ExpireResponse":{"type":"object","description":"Response for expire operation","required":["success"],"properties":{"success":{"type":"boolean","description":"True if expiration was set, false if key doesn't exist"}}},"ExplorerSupportResponse":{"type":"object","required":["supported","service_type","capabilities","hierarchy"],"properties":{"capabilities":{"type":"array","items":{"type":"string"},"description":"Capabilities supported by this service","example":["sql"]},"filter_schema":{"description":"JSON Schema for filter format with embedded UI hints (if supported)"},"hierarchy":{"type":"array","items":{"$ref":"#/components/schemas/HierarchyLevel"},"description":"Hierarchy levels (describes the navigation structure)"},"reason":{"type":["string","null"],"description":"Reason why explorer is not supported (if applicable)"},"service_type":{"type":"string","description":"Service type","example":"postgres"},"supported":{"type":"boolean","description":"Whether the service supports query explorer functionality","example":true}}},"ExtendTimeoutBody":{"type":"object","properties":{"duration":{"type":["integer","null"],"format":"int64","description":"`@vercel/sandbox`-compatible alternative — duration in milliseconds.\nUsed when `extra_secs` is absent.","minimum":0},"extra_secs":{"type":["integer","null"],"format":"int64","description":"Extra seconds to add to the existing `expires_at` (temps-native).","minimum":0}}},"ExternalImageResponse":{"type":"object","required":["id","project_id","image_ref","pushed_at","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"digest":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"image_ref":{"type":"string"},"metadata":{},"project_id":{"type":"integer","format":"int32"},"pushed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"size_bytes":{"type":["integer","null"],"format":"int64"},"tag":{"type":["string","null"]}}},"ExternalServiceBackupResponse":{"type":"object","description":"Response type for external service backup","required":["id","service_id","backup_id","backup_type","state","started_at","s3_location","metadata","compression_type","created_by"],"properties":{"backup_id":{"type":"integer","format":"int32"},"backup_type":{"type":"string"},"checksum":{"type":["string","null"]},"compression_type":{"type":"string"},"created_by":{"type":"integer","format":"int32"},"error_message":{"type":["string","null"]},"expires_at":{"type":["string","null"],"example":"2025-02-15T14:30:00.123Z"},"finished_at":{"type":["string","null"],"example":"2025-01-15T14:35:00.456Z"},"id":{"type":"integer","format":"int32"},"metadata":{},"s3_location":{"type":"string"},"service_id":{"type":"integer","format":"int32"},"size_bytes":{"type":["integer","null"],"format":"int64"},"started_at":{"type":"string","example":"2025-01-15T14:30:00.123Z"},"state":{"type":"string"}}},"ExternalServiceDetails":{"type":"object","required":["service","sensitive_parameters"],"properties":{"current_parameters":{"type":["object","null"],"additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"parameter_schema":{},"sensitive_parameters":{"type":"array","items":{"type":"string"},"description":"Parameter names whose values are masked in `current_parameters` and\nmay be fetched only through the audited reveal endpoint."},"service":{"$ref":"#/components/schemas/ExternalServiceInfo"}}},"ExternalServiceInfo":{"type":"object","required":["id","name","service_type","status","created_at","updated_at","topology"],"properties":{"connection_info":{"type":["string","null"]},"created_at":{"type":"string"},"error_message":{"type":["string","null"],"description":"Error message from failed initialization."},"id":{"type":"integer","format":"int32"},"members":{"type":"array","items":{"$ref":"#/components/schemas/ServiceMemberInfo"},"description":"Cluster members (empty for standalone services)."},"metrics_enabled":{"type":"boolean","description":"Whether metric collection is enabled for this service. The UI uses this\nto decide whether to poll the monitoring endpoints."},"name":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Node ID where the service runs. Null means control plane (local)."},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"},"status":{"type":"string"},"topology":{"type":"string","description":"Service topology: \"standalone\" (single container) or \"cluster\" (HA multi-member).","example":"standalone"},"updated_at":{"type":"string"},"version":{"type":["string","null"]}}},"ExternalServiceSummary":{"type":"object","description":"Summary of the external service that owns a backup. Only populated for\nexternal-service backups (Redis, Postgres, etc.); absent for control-plane\nbackups.","required":["id","name","service_type"],"properties":{"id":{"type":"integer","format":"int32","description":"Database id of the external service."},"name":{"type":"string","description":"Human-readable service name (e.g. \"redis-prod\")."},"service_type":{"type":"string","description":"Service type string (e.g. \"postgres\", \"redis\", \"mongodb\").","example":"postgres"}}},"FieldResponse":{"type":"object","required":["name","field_type","nullable"],"properties":{"field_type":{"type":"string","description":"Field type (Int32, String, Timestamp, etc.)","example":"Int64"},"name":{"type":"string","description":"Field name","example":"id"},"nullable":{"type":"boolean","description":"Whether the field is nullable","example":false}}},"FiringSeriesEntry":{"type":"object","description":"A single currently-firing series for a dynamic alert rule, snapshotted from\nthe evaluator's in-memory per-series firing map at read time (ADR-026 Phase 3).","required":["series_key","series_label"],"properties":{"alarm_id":{"type":["integer","null"],"format":"int32","description":"The open alarm's id, when one was created (absent if suppressed)."},"series_key":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"The series' label pairs, e.g. `[[\"endpoint\",\"/checkout\"],[\"region\",\"eu-west\"]]`."},"series_label":{"type":"string","description":"The human-readable joined label, e.g. `endpoint=/checkout, region=eu-west`."}}},"ForecastAlgorithm":{"type":"string","description":"Forecast model family.","enum":["linear","seasonal"]},"ForecastParams":{"type":"object","description":"Forecast detector parameters (stub — not yet evaluated).","required":["forecast_horizon_secs","comparator","threshold"],"properties":{"algorithm":{"$ref":"#/components/schemas/ForecastAlgorithm"},"comparator":{"$ref":"#/components/schemas/Comparator","description":"Comparator + threshold the *forecast* is checked against."},"deviations":{"type":"number","format":"double"},"forecast_horizon_secs":{"type":"integer","format":"int32","description":"How far ahead to project before checking the breach condition."},"threshold":{"type":"number","format":"double"}}},"FullError":{"type":"object","required":["id","ts","error_group_id","fingerprint","error_class"],"properties":{"data":{"description":"Full JSONB blob from `error_events.data` — stack trace, breadcrumbs,\nrequest context, everything. Schema is documented per source SDK."},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_class":{"type":"string"},"error_group_id":{"type":"integer","format":"int32"},"fingerprint":{"type":"string"},"id":{"type":"integer","format":"int64"},"message":{"type":["string","null"]},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"FullEvent":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/FullRequest"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["request"]}}}]},{"allOf":[{"$ref":"#/components/schemas/FullError"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/RevenueRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["revenue"]}}}]},{"allOf":[{"$ref":"#/components/schemas/SpanRow","description":"`SpanRow.attributes` is the truncated form; re-fetching returns\nthe same shape so the panel has a stable contract."},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["span"]}}}],"description":"`SpanRow.attributes` is the truncated form; re-fetching returns\nthe same shape so the panel has a stable contract."}],"description":"One un-truncated row, returned by the `/full/{type}/{id}` endpoint when\nthe user clicks \"Show full\". Same shape as the list rows, but with the\nraw heavy fields restored (no truncation flags) so the side panel can\nrender the long form."},"FullRequest":{"type":"object","required":["id","ts","method","host","path","status"],"properties":{"client_ip":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_group_id":{"type":["integer","null"],"format":"int32"},"host":{"type":"string"},"id":{"type":"string","description":"The request's unique `request_id` — same identity the list rows carry\n(backend-agnostic; ClickHouse rows have no serial PK)."},"latency_ms":{"type":["integer","null"],"format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"referrer":{"type":["string","null"]},"request_headers":{},"response_headers":{},"status":{"type":"integer","format":"int32"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"},"user_agent":{"type":["string","null"]}}},"FunnelMetricsResponse":{"type":"object","required":["funnel_id","funnel_name","total_entries","step_conversions","overall_conversion_rate","average_completion_time_seconds"],"properties":{"average_completion_time_seconds":{"type":"number","format":"double"},"funnel_id":{"type":"integer","format":"int32"},"funnel_name":{"type":"string"},"overall_conversion_rate":{"type":"number","format":"double"},"step_conversions":{"type":"array","items":{"$ref":"#/components/schemas/StepConversionResponse"}},"total_entries":{"type":"integer","format":"int64","minimum":0}}},"FunnelResponse":{"type":"object","required":["id","name","is_active","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"string"}}},"GatewayStatus":{"type":"object","description":"Detailed gateway container status surfaced to the settings UI.","required":["present","running","health","container_name","expected_image","drift","auto_upgrade"],"properties":{"auto_upgrade":{"type":"boolean","description":"True if `auto_upgrade` is enabled in settings."},"container_name":{"type":"string","description":"Container name."},"drift":{"type":"boolean","description":"True when `image != expected_image` and the container is present."},"expected_image":{"type":"string","description":"The image the supervisor *expects* (from settings/constant). If this\ndiffers from `image`, the UI shows a \"drift\" badge."},"health":{"type":"string","description":"Higher-level health label: \"running\" | \"restarting\" | \"crash_looping\"\n| \"stopped\" | \"missing\". UI should prefer this over `running`."},"host_port":{"type":["integer","null"],"format":"int32","description":"Host port that the container's :8080 is published on.","minimum":0},"image":{"type":["string","null"],"description":"Image reference the container was created with (e.g.\n`ghcr.io/gotempsh/temps-preview-gateway:latest`)."},"image_digest":{"type":["string","null"],"description":"Image digest if available (e.g. `sha256:…`)."},"last_error":{"type":["string","null"],"description":"Error string Docker recorded for the container (e.g. startup failure)."},"last_exit_code":{"type":["integer","null"],"format":"int64","description":"Exit code of the last run, if the container is not currently running."},"network":{"type":["string","null"],"description":"Network the container is attached to (should be `temps-sandbox-net`)."},"present":{"type":"boolean","description":"Whether the container exists at all."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Number of times Docker has restarted the container."},"running":{"type":"boolean","description":"Whether the container is currently running."},"started_at":{"type":["string","null"],"description":"ISO 8601 timestamp the container was started at, if running."}}},"GenAiEvent":{"type":"object","description":"A GenAI-related event extracted from span events.\n\nCovers `gen_ai.client.inference.operation.details` and `gen_ai.evaluation.result`\nevents per the OTel GenAI semantic conventions.","required":["span_id","trace_id","event_name","timestamp","attributes"],"properties":{"attributes":{"type":"object","description":"All event attributes.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"event_name":{"type":"string"},"span_id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"trace_id":{"type":"string"}}},"GenAiSpanDetail":{"type":"object","description":"A single GenAI span with extracted semantic convention fields.\n\nFields are aligned with the OpenTelemetry GenAI Semantic Conventions spec:\n","required":["span_id","name","kind","start_time","duration_ms","status_code","attributes"],"properties":{"agent_description":{"type":["string","null"],"description":"Agent description from `gen_ai.agent.description`."},"agent_id":{"type":["string","null"],"description":"Agent identifier from `gen_ai.agent.id`."},"agent_name":{"type":["string","null"],"description":"Agent name from `gen_ai.agent.name`."},"agent_version":{"type":["string","null"],"description":"Agent version from `gen_ai.agent.version`."},"attributes":{"type":"object","description":"All span attributes for extensibility.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"aws_bedrock_guardrail_id":{"type":["string","null"],"description":"AWS Bedrock guardrail ID from `aws.bedrock.guardrail.id`."},"aws_bedrock_knowledge_base_id":{"type":["string","null"],"description":"AWS Bedrock knowledge base ID from `aws.bedrock.knowledge_base.id`."},"azure_resource_provider_namespace":{"type":["string","null"],"description":"Azure resource provider namespace from `azure.resource_provider.namespace`."},"cache_creation_input_tokens":{"type":["integer","null"],"format":"int64","description":"Tokens written to provider cache from `gen_ai.usage.cache_creation.input_tokens`."},"cache_read_input_tokens":{"type":["integer","null"],"format":"int64","description":"Tokens served from provider cache from `gen_ai.usage.cache_read.input_tokens`."},"conversation_id":{"type":["string","null"],"description":"Unique conversation/session/thread ID from `gen_ai.conversation.id`."},"data_source_id":{"type":["string","null"],"description":"Data source identifier from `gen_ai.data_source.id`."},"duration_ms":{"type":"number","format":"double"},"embeddings_dimension_count":{"type":["integer","null"],"format":"int64","description":"Output embedding dimensions from `gen_ai.embeddings.dimension.count`."},"error_type":{"type":["string","null"],"description":"Error type from `error.type` when the span status is ERROR."},"gen_ai_model":{"type":["string","null"],"description":"The requested model from `gen_ai.request.model`."},"gen_ai_operation":{"type":["string","null"],"description":"The operation type from `gen_ai.operation.name` (e.g. \"chat\", \"embeddings\", \"execute_tool\")."},"gen_ai_response_model":{"type":["string","null"],"description":"The model that actually generated the response from `gen_ai.response.model`."},"gen_ai_system":{"type":["string","null"],"description":"The GenAI provider from `gen_ai.provider.name` (falls back to deprecated `gen_ai.system`)."},"input_messages":{"type":["string","null"],"description":"Chat history input from `gen_ai.input.messages` (opt-in, JSON string)."},"input_tokens":{"type":["integer","null"],"format":"int64"},"kind":{"$ref":"#/components/schemas/SpanKind"},"name":{"type":"string"},"openai_api_type":{"type":["string","null"],"description":"OpenAI API type from `openai.api.type` (chat_completions, responses)."},"openai_request_service_tier":{"type":["string","null"],"description":"Requested service tier from `openai.request.service_tier`."},"openai_response_service_tier":{"type":["string","null"],"description":"Actual service tier from `openai.response.service_tier`."},"openai_system_fingerprint":{"type":["string","null"],"description":"System fingerprint from `openai.response.system_fingerprint`."},"output_messages":{"type":["string","null"],"description":"Model output from `gen_ai.output.messages` (opt-in, JSON string)."},"output_tokens":{"type":["integer","null"],"format":"int64"},"output_type":{"type":["string","null"],"description":"Output content type from `gen_ai.output.type` (text, json, image, speech)."},"parent_span_id":{"type":["string","null"]},"request_choice_count":{"type":["integer","null"],"format":"int64","description":"Number of choices requested from `gen_ai.request.choice.count`."},"request_encoding_formats":{"type":["array","null"],"items":{"type":"string"},"description":"Requested encoding formats from `gen_ai.request.encoding_formats`."},"request_frequency_penalty":{"type":["number","null"],"format":"double","description":"Frequency penalty from `gen_ai.request.frequency_penalty`."},"request_max_tokens":{"type":["integer","null"],"format":"int64","description":"Max tokens from `gen_ai.request.max_tokens`."},"request_presence_penalty":{"type":["number","null"],"format":"double","description":"Presence penalty from `gen_ai.request.presence_penalty`."},"request_seed":{"type":["integer","null"],"format":"int64","description":"Seed for reproducibility from `gen_ai.request.seed`."},"request_stop_sequences":{"type":["array","null"],"items":{"type":"string"},"description":"Stop sequences from `gen_ai.request.stop_sequences`."},"request_temperature":{"type":["number","null"],"format":"double","description":"Temperature setting from `gen_ai.request.temperature`."},"request_top_k":{"type":["number","null"],"format":"double","description":"Top-k setting from `gen_ai.request.top_k`."},"request_top_p":{"type":["number","null"],"format":"double","description":"Top-p setting from `gen_ai.request.top_p`."},"response_finish_reasons":{"type":["array","null"],"items":{"type":"string"},"description":"Reasons the model stopped from `gen_ai.response.finish_reasons` (e.g. [\"stop\"])."},"response_id":{"type":["string","null"],"description":"Unique completion ID from `gen_ai.response.id` (e.g. \"chatcmpl-123\")."},"retrieval_documents":{"type":["string","null"],"description":"Retrieved documents from `gen_ai.retrieval.documents` (opt-in, JSON string)."},"retrieval_query_text":{"type":["string","null"],"description":"Retrieval query text from `gen_ai.retrieval.query.text` (opt-in)."},"server_address":{"type":["string","null"],"description":"GenAI server address from `server.address`."},"server_port":{"type":["integer","null"],"format":"int64","description":"GenAI server port from `server.port`."},"span_id":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"system_instructions":{"type":["string","null"],"description":"System instructions from `gen_ai.system_instructions` (opt-in, JSON string)."},"tool_call_arguments":{"type":["string","null"],"description":"Tool call arguments from `gen_ai.tool.call.arguments` (opt-in, JSON string)."},"tool_call_id":{"type":["string","null"],"description":"Tool call ID from `gen_ai.tool.call.id`."},"tool_call_result":{"type":["string","null"],"description":"Tool call result from `gen_ai.tool.call.result` (opt-in, JSON string)."},"tool_definitions":{"type":["string","null"],"description":"Tool definitions from `gen_ai.tool.definitions` (opt-in, JSON string)."},"tool_description":{"type":["string","null"],"description":"Tool description from `gen_ai.tool.description`."},"tool_name":{"type":["string","null"],"description":"Tool name from `gen_ai.tool.name`."},"tool_type":{"type":["string","null"],"description":"Tool type from `gen_ai.tool.type` (function, extension, datastore)."}}},"GenAiTraceDetailResponse":{"type":"object","required":["trace_id","spans","span_count","events","event_count"],"properties":{"event_count":{"type":"integer","minimum":0},"events":{"type":"array","items":{"$ref":"#/components/schemas/GenAiEvent"}},"span_count":{"type":"integer","minimum":0},"spans":{"type":"array","items":{"$ref":"#/components/schemas/GenAiSpanDetail"}},"trace_id":{"type":"string"}}},"GenAiTraceSummariesResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GenAiTraceSummary"}},"total":{"type":"integer","format":"int64","minimum":0}}},"GenAiTraceSummary":{"type":"object","description":"Summary of a GenAI conversation — aggregated from OTel spans with `gen_ai.*` attributes.","required":["trace_id","root_span_name","service_name","start_time","duration_ms","span_count","error_count"],"properties":{"duration_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"gen_ai_model":{"type":["string","null"],"description":"The requested model from `gen_ai.request.model`."},"gen_ai_operation":{"type":["string","null"],"description":"The operation type from `gen_ai.operation.name` (e.g. \"chat\", \"embeddings\")."},"gen_ai_system":{"type":["string","null"],"description":"The GenAI provider (e.g. \"openai\", \"anthropic\") from `gen_ai.provider.name`."},"root_span_name":{"type":"string"},"service_name":{"type":"string"},"span_count":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"total_cache_creation_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total cache-creation input tokens across all spans."},"total_cache_read_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total cache-read input tokens across all spans."},"total_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total input tokens across all spans in this trace."},"total_output_tokens":{"type":["integer","null"],"format":"int64","description":"Total output tokens across all spans in this trace."},"trace_id":{"type":"string"}}},"GeneralStatsQuery":{"type":"object","required":["start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"start_date":{"type":"string","format":"date-time"}}},"GeneralStatsResponse":{"type":"object","required":["total_unique_visitors","total_visits","total_page_views","total_events","total_projects","avg_bounce_rate","avg_engagement_rate","project_breakdown"],"properties":{"avg_bounce_rate":{"type":"number","format":"double"},"avg_engagement_rate":{"type":"number","format":"double"},"page_views_trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change in page views vs previous period"},"previous_page_views":{"type":["integer","null"],"format":"int64","description":"Previous period page views"},"previous_unique_visitors":{"type":["integer","null"],"format":"int64","description":"Previous period unique visitors (same duration, shifted back)"},"project_breakdown":{"type":"array","items":{"$ref":"#/components/schemas/ProjectStatsBreakdown"}},"total_events":{"type":"integer","format":"int64"},"total_page_views":{"type":"integer","format":"int64"},"total_projects":{"type":"integer","format":"int64"},"total_unique_visitors":{"type":"integer","format":"int64"},"total_visits":{"type":"integer","format":"int64"},"visitors_trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change in unique visitors vs previous period"}}},"GenerateDockerfileRequest":{"type":"object","description":"Request body for generating a Dockerfile from a preset","properties":{"build_command":{"type":["string","null"],"description":"Custom build command (overrides preset default)","example":"npm run build"},"install_command":{"type":["string","null"],"description":"Custom install command (overrides preset default)","example":"npm ci"},"output_dir":{"type":["string","null"],"description":"Output directory for static builds","example":"dist"},"package_manager":{"type":["string","null"],"description":"Package manager used by the project (npm, yarn, pnpm, bun)\nIf not provided, defaults to npm","example":"npm"},"project_name":{"type":["string","null"],"description":"Project name/slug used for container naming","example":"my-app"},"use_buildkit":{"type":"boolean","description":"Whether to use BuildKit cache mounts for faster builds"}}},"GenerateDockerfileResponse":{"type":"object","description":"Response containing a generated Dockerfile and build arguments","required":["dockerfile","build_args","preset"],"properties":{"build_args":{"type":"object","description":"Build arguments to pass to `docker build --build-arg KEY=VALUE`","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"dockerfile":{"type":"string","description":"The generated Dockerfile content"},"preset":{"type":"string","description":"The preset slug used for generation"}}},"GenerateJoinTokenResponse":{"type":"object","description":"Response returned when a join token is generated (plaintext shown once)","required":["token","message"],"properties":{"message":{"type":"string"},"token":{"type":"string","description":"The plaintext join token — shown only once, save it now"}}},"GeoLocationResponse":{"type":"object","description":"Response containing geolocation information for an IP address","required":["ip","is_eu"],"properties":{"city":{"type":["string","null"],"description":"City name","example":"Mountain View"},"country":{"type":["string","null"],"description":"Country name","example":"United States"},"country_code":{"type":["string","null"],"description":"ISO country code (2 letters)","example":"US"},"ip":{"type":"string","description":"IP address that was geolocated","example":"8.8.8.8"},"is_eu":{"type":"boolean","description":"Whether the IP is in the European Union","example":false},"latitude":{"type":["number","null"],"format":"double","description":"Latitude coordinate","example":37.386},"longitude":{"type":["number","null"],"format":"double","description":"Longitude coordinate","example":-122.0838},"region":{"type":["string","null"],"description":"Region/state name","example":"California"},"timezone":{"type":["string","null"],"description":"Timezone identifier","example":"America/Los_Angeles"}}},"GeoRestrictionsConfig":{"type":"object","description":"Geographic restrictions configuration (future feature)","properties":{"allowedCountries":{"type":"array","items":{"type":"string"},"description":"Allow traffic only from specific countries"},"blockedCountries":{"type":"array","items":{"type":"string"},"description":"Block traffic from specific countries (ISO 3166-1 alpha-2 codes)"}}},"GetDeploymentsParams":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64"},"per_page":{"type":["integer","null"],"format":"int64"}}},"GetEnvironmentVariablesQuery":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"service_id":{"type":["integer","null"],"format":"int32","description":"Required by integration-value reveals to bind the plaintext response to\nthe exact service displayed by the client."},"var_id":{"type":["integer","null"],"format":"int32","description":"Exact manual env-var row to reveal. Required by the dashboard so\nduplicate keys on disjoint environments cannot cross-reveal."}}},"GetFunnelMetricsQuery":{"type":"object","properties":{"country_code":{"type":["string","null"]},"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":["string","null"],"format":"date-time"}}},"GetOrCreateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"}}},"GetProjectSecretsQuery":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"}}},"GetProjectSessionReplaysQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"project_id":{"type":"integer","format":"int32"}}},"GetProjectSessionReplaysResponse":{"type":"object","required":["sessions","page","per_page","total_count"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}},"total_count":{"type":"integer","format":"int64","minimum":0}}},"GetRequest":{"type":"object","description":"Request to get a value by key","required":["key"],"properties":{"key":{"type":"string","description":"The key to retrieve","example":"user:123"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"GetResponse":{"type":"object","description":"Response for get operation","properties":{"value":{"description":"The value, or null if not found"}}},"GetSessionReplayResponse":{"type":"object","required":["session"],"properties":{"session":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}}},"GetUniqueEventsQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"page_size":{"type":["integer","null"],"format":"int64","minimum":0}}},"GetVisitorSessionsQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0}}},"GetVisitorSessionsResponse":{"type":"object","required":["sessions","page","per_page","total_count"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}},"total_count":{"type":"integer","minimum":0}}},"GitPushEvent":{"type":"object","description":"Git push event information that triggered the deployment","required":["repo","owner","branch","commit"],"properties":{"branch":{"type":"string","description":"Branch that was pushed"},"commit":{"type":"string","description":"Commit SHA"},"owner":{"type":"string","description":"Repository owner/organization"},"repo":{"type":"string","description":"Repository name"}}},"GitRefResponse":{"type":"object","description":"Git repository reference response","required":["url","ref"],"properties":{"path":{"type":["string","null"],"description":"Path within the repository (for monorepos)"},"ref":{"type":"string","description":"Git reference (branch, tag, or commit)"},"url":{"type":"string","description":"Git repository URL"}}},"GitSourcePlan":{"type":"object","description":"Git repository the source platform deploys from","required":["owner","repo","branch","is_public"],"properties":{"branch":{"type":"string","description":"Branch the source platform deploys"},"clone_url":{"type":["string","null"],"description":"Full clone URL, e.g. `https://github.com/owner/repo.git`"},"is_public":{"type":"boolean","description":"True when the repository is public (no credentials on the source\nplatform) — the project can then build without a git provider\nconnection."},"owner":{"type":"string","description":"Repository owner (organization or user)"},"repo":{"type":"string","description":"Repository name"}}},"GlobalConversationResponse":{"type":"object","description":"A conversation in the unified cross-project switcher: carries the project it\nbelongs to (name/slug) so the UI can show where the chat was started and\nlink back to the source.","required":["public_id","project_id","context_type","context_id","status","created_at","last_activity_at"],"properties":{"context_id":{"type":"string"},"context_type":{"type":"string"},"created_at":{"type":"string"},"last_activity_at":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":["string","null"]},"project_slug":{"type":["string","null"]},"public_id":{"type":"string"},"status":{"type":"string"},"title":{"type":["string","null"]}}},"GlobalEventStatsResponse":{"type":"object","required":["delivered","opened","clicked","bounced","complained"],"properties":{"bounce_rate":{"type":["number","null"],"format":"double"},"bounced":{"type":"integer","format":"int64","minimum":0},"click_rate":{"type":["number","null"],"format":"double"},"clicked":{"type":"integer","format":"int64","minimum":0},"complained":{"type":"integer","format":"int64","minimum":0},"delivered":{"type":"integer","format":"int64","minimum":0},"open_rate":{"type":["number","null"],"format":"double"},"opened":{"type":"integer","format":"int64","minimum":0}}},"GlobalMrrResponse":{"type":"object","required":["currency","current_mrr_minor","previous_mrr_minor"],"properties":{"change_percentage":{"type":["number","null"],"format":"double","description":"Percentage change vs 24h ago. Null when previous MRR is zero\n(no baseline to compare against)."},"currency":{"type":"string"},"current_mrr_minor":{"type":"integer","format":"int64"},"previous_mrr_minor":{"type":"integer","format":"int64","description":"MRR 24h before now, reconstructed from the event log."}}},"GlobalRecentEventResponse":{"type":"object","required":["id","project_id","project_name","occurred_at","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"mrr_minor":{"type":["integer","null"],"format":"int64"},"occurred_at":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"}}},"GlobalRevenueSummaryResponse":{"type":"object","required":["currency","current_mrr_minor","paid_last_30d_minor","refunded_last_30d_minor","paid_all_time_minor","refunded_all_time_minor","active_subscriptions","active_customers","transactions_last_30d"],"properties":{"active_customers":{"type":"integer","format":"int64"},"active_subscriptions":{"type":"integer","format":"int64"},"currency":{"type":"string"},"current_mrr_minor":{"type":"integer","format":"int64"},"paid_all_time_minor":{"type":"integer","format":"int64"},"paid_last_30d_minor":{"type":"integer","format":"int64"},"refunded_all_time_minor":{"type":"integer","format":"int64"},"refunded_last_30d_minor":{"type":"integer","format":"int64"},"transactions_last_30d":{"type":"integer","format":"int64"}}},"GroupedPageMetric":{"type":"object","required":["group_key","events"],"properties":{"cls":{"type":["number","null"],"format":"float"},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 code of the group's country. Populated for the\ngeographic dimensions (country/region/city) so clients can match map\ngeometries without name-based lookups; null otherwise."},"events":{"type":"integer","format":"int64"},"fcp":{"type":["number","null"],"format":"float"},"group_key":{"type":"string"},"inp":{"type":["number","null"],"format":"float"},"lcp":{"type":["number","null"],"format":"float"},"ttfb":{"type":["number","null"],"format":"float"}}},"GroupedPageMetricsQuery":{"allOf":[{"$ref":"#/components/schemas/SpeedSegmentFilters","description":"Segment filters — same shape as `PerformanceMetricsQuery`."},{"type":"object","required":["start_date","end_date","project_id","group_by"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"],"description":"Device type filter: \"desktop\" or \"mobile\""},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"group_by":{"type":"string"},"include_bots":{"type":["boolean","null"],"description":"Include crawler/datacenter (bot) samples. Defaults to false."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"GroupedPageMetricsResponse":{"type":"object","required":["groups","total_events","grouped_by"],"properties":{"grouped_by":{"type":"string"},"groups":{"type":"array","items":{"$ref":"#/components/schemas/GroupedPageMetric"}},"total_events":{"type":"integer","format":"int64"}}},"HasAnalyticsEventsResponse":{"type":"object","required":["has_events"],"properties":{"has_events":{"type":"boolean"}}},"HasErrorGroupsResponse":{"type":"object","required":["has_error_groups"],"properties":{"has_error_groups":{"type":"boolean"}}},"HasEventsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"HasEventsResponse":{"type":"object","required":["has_events"],"properties":{"has_events":{"type":"boolean"}}},"HasMetricsQuery":{"type":"object","required":["project_id"],"properties":{"project_id":{"type":"integer","format":"int32"}}},"HasMetricsResponse":{"type":"object","required":["has_metrics"],"properties":{"has_metrics":{"type":"boolean"}}},"HealthCheckConfiguration":{"type":"object","description":"Health check configuration","required":["port","interval","timeout","retries"],"properties":{"http_path":{"type":["string","null"],"description":"HTTP path to check (if applicable)"},"interval":{"type":"integer","format":"int32","description":"Interval between checks (seconds)","minimum":0},"port":{"type":"integer","format":"int32","description":"Port to check","minimum":0},"retries":{"type":"integer","format":"int32","description":"Number of retries before marking unhealthy","minimum":0},"timeout":{"type":"integer","format":"int32","description":"Timeout for each check (seconds)","minimum":0}}},"HealthCheckEntryResponse":{"type":"object","required":["checked_at","status"],"properties":{"checked_at":{"type":"string","description":"ISO 8601 timestamp of when the probe ran.","example":"2026-04-22T11:30:00Z"},"error_message":{"type":["string","null"],"description":"Present only when the probe failed or was degraded."},"response_time_ms":{"type":["integer","null"],"format":"int32","description":"TCP connect latency in milliseconds."},"status":{"type":"string","description":"\"operational\" | \"degraded\" | \"down\"","example":"operational"}}},"HealthResponse":{"type":"object","required":["summaries"],"properties":{"summaries":{"type":"array","items":{"$ref":"#/components/schemas/HealthSummary"}}}},"HealthStatus":{"type":"string","description":"Overall health status.","enum":["healthy","degraded","down","unknown"]},"HealthSummary":{"type":"object","description":"Pre-computed health summary for a project environment.","required":["project_id","service_name","status","uptime_pct","error_rate","p95_latency_ms","cpu_usage_pct","memory_usage_pct","computed_at"],"properties":{"computed_at":{"type":"string","format":"date-time"},"cpu_usage_pct":{"type":"number","format":"double"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_rate":{"type":"number","format":"double"},"last_deploy_at":{"type":["string","null"],"format":"date-time"},"last_deploy_id":{"type":["integer","null"],"format":"int32"},"memory_usage_pct":{"type":"number","format":"double"},"p95_latency_ms":{"type":"number","format":"double"},"project_id":{"type":"integer","format":"int32"},"service_name":{"type":"string"},"status":{"$ref":"#/components/schemas/HealthStatus"},"uptime_pct":{"type":"number","format":"double"}}},"HeartbeatApiRequest":{"type":"object","properties":{"capacity":{"description":"Resource capacity/usage info as JSON (cpu_usage, memory_usage, etc.)"},"containers":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ContainerInventoryItem"},"description":"Container inventory for reconciliation (sent on first heartbeat after agent startup).\nEach entry has `container_id` and `container_name` of temps-managed containers."},"labels":{"description":"Updated node labels for scheduling (allows runtime label changes)."}}},"HeartbeatResponse":{"type":"object","required":["status","message"],"properties":{"message":{"type":"string"},"status":{"type":"string"}}},"HierarchyLevel":{"type":"object","description":"Describes a level in the data source hierarchy","required":["level","name","container_type","can_list_containers","can_list_entities"],"properties":{"can_list_containers":{"type":"boolean","description":"Can list containers at this level?","example":true},"can_list_entities":{"type":"boolean","description":"Can list entities at this level?","example":false},"container_type":{"type":"string","description":"Type of container at this level","example":"database"},"level":{"type":"integer","format":"int32","description":"Level number (0 = root)","example":0,"minimum":0},"name":{"type":"string","description":"Human-readable name for this level","example":"root"}}},"HistogramSummary":{"type":"object","description":"An explicit-bucket histogram aggregated over a time bucket.\n\nCarries the reduced scalars (count/sum/min/max) plus the explicit bucket\nlayout — `bounds` (the upper bounds) and `bucket_counts` (observation counts,\nsummed element-wise across the window; length is `bounds.len() + 1`, the last\nentry being the +Inf overflow bucket). With these, a caller can reconstruct\nany quantile (e.g. p95) via cumulative-count interpolation.","required":["count","sum","bounds","bucket_counts"],"properties":{"bounds":{"type":"array","items":{"type":"number","format":"double"},"description":"Explicit bucket upper bounds (OTLP `explicit_bounds`), ascending."},"bucket_counts":{"type":"array","items":{"type":"integer","format":"int64","minimum":0},"description":"Per-bucket observation counts summed element-wise across the window.\nLength is `bounds.len() + 1` (the trailing element is the +Inf bucket)."},"count":{"type":"integer","format":"int64","description":"Total observation count summed across the bucket window.","minimum":0},"max":{"type":["number","null"],"format":"double","description":"Maximum observed value, when reported by the producer."},"min":{"type":["number","null"],"format":"double","description":"Minimum observed value, when reported by the producer."},"sum":{"type":"number","format":"double","description":"Sum of observed values across the bucket window."}}},"HostnameChange":{"type":"object","description":"A single generated-hostname change in a flatten preview/apply.","required":["kind","id","old","new"],"properties":{"id":{"type":"integer","format":"int32","description":"Row id of the affected record."},"kind":{"type":"string","description":"`\"deployment\"` or `\"environment\"`."},"new":{"type":"string"},"old":{"type":"string"}}},"HostnamePreviewResponse":{"type":"object","description":"Combined preview of a hostname-mode change.","required":["hostname_changes","dns_changes","total"],"properties":{"dns_changes":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordChange"}},"hostname_changes":{"type":"array","items":{"$ref":"#/components/schemas/HostnameChange"}},"total":{"type":"integer","minimum":0},"zone_access_ok":{"type":["boolean","null"],"description":"Whether the provider token can manage this zone (None if not checked)."}}},"HourlyPageSessions":{"type":"object","required":["timestamp","session_count","event_count","avg_duration_seconds"],"properties":{"avg_duration_seconds":{"type":"number","format":"double"},"event_count":{"type":"integer","format":"int64"},"session_count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"HourlyVisitsQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (page views), sessions (unique sessions), or visitors (unique visitors)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"HttpChallengeDebugResponse":{"type":"object","required":["domain","challenge_exists","dns_a_records","dns_aaaa_records"],"properties":{"challenge_exists":{"type":"boolean"},"challenge_token":{"type":["string","null"]},"challenge_url":{"type":["string","null"],"description":"The full URL that Let's Encrypt will try to access to validate the challenge"},"dns_a_records":{"type":"array","items":{"type":"string"},"description":"IPv4 addresses the domain points to"},"dns_aaaa_records":{"type":"array","items":{"type":"string"},"description":"IPv6 addresses the domain points to"},"dns_error":{"type":["string","null"],"description":"Any DNS resolution errors"},"domain":{"type":"string"},"validation_url":{"type":["string","null"],"description":"The ACME validation URL (internal to ACME protocol)"}}},"ImportCredentials":{"type":"object","description":"Platform-specific credentials for accessing the source system.\n\nFor platforms like Vercel and Railway, this contains the API token.\nFor self-hosted platforms like Coolify and Dokploy, this also contains\nthe `base_url` of the instance.\n\nLocal importers (Docker) can use `ImportCredentials::none()`.","properties":{"base_url":{"type":["string","null"],"description":"Base URL override (for self-hosted platforms like Coolify, Dokploy)\n\nExample: `https://coolify.example.com`"},"extra":{"type":"object","description":"Additional platform-specific parameters","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"team_id":{"type":["string","null"],"description":"Team or organization ID (for platforms with team scoping like Vercel)"},"token":{"type":["string","null"],"description":"API token / bearer token for the source platform"}}},"ImportExecutionStatus":{"type":"string","description":"Import execution status","enum":["pending","inprogress","completed","failed"]},"ImportExternalServiceRequest":{"type":"object","description":"Request to import a Docker container as a managed service","required":["name","service_type","parameters","container_id"],"properties":{"container_id":{"type":"string","description":"Container ID or name to import","example":"abc123def456"},"name":{"type":"string","description":"Name to register the service as in Temps","example":"production-database"},"parameters":{"type":"object","description":"Service configuration parameters","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute","description":"Service type"},"version":{"type":["string","null"],"description":"Optional version override"}}},"ImportOutcomeResponse":{"type":"object","required":["rows_read","inserted","updated","skipped_stale","skipped_invalid","errors"],"properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ImportRowErrorResponse"}},"inserted":{"type":"integer","minimum":0},"rows_read":{"type":"integer","minimum":0},"skipped_invalid":{"type":"integer","minimum":0},"skipped_stale":{"type":"integer","minimum":0},"updated":{"type":"integer","minimum":0}}},"ImportPlan":{"type":"object","description":"Complete import plan describing all operations to onboard a workload.\n\nThe plan is generated from a snapshot and presented to the user for review\nbefore any resources are created. Users can modify individual items\n(skip services, change actions) before approving execution.","required":["version","source","source_id","project","environment","deployment","summary","metadata"],"properties":{"additional_deployments":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentConfiguration"},"description":"Additional deployments (workers, cron jobs, etc.)"},"cost_analysis":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CostAnalysis","description":"Cost, overprovisioning, and savings analysis. Populated by importers\nthat can observe the whole source cluster (currently Kubernetes);\n`None` for container/platform imports."}]},"deployment":{"$ref":"#/components/schemas/DeploymentConfiguration","description":"Primary deployment configuration"},"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainPlan"},"description":"Custom domains to migrate"},"environment":{"$ref":"#/components/schemas/EnvironmentConfiguration","description":"Environment configuration"},"metadata":{"$ref":"#/components/schemas/PlanMetadata","description":"Plan metadata"},"project":{"$ref":"#/components/schemas/ProjectConfiguration","description":"Project configuration"},"services":{"type":"array","items":{"$ref":"#/components/schemas/ServicePlan"},"description":"Services to migrate (databases, caches, blob stores)\n\nEach service has an `action` field the user can change before execution."},"source":{"type":"string","description":"Source system this plan was generated from"},"source_id":{"type":"string","description":"Source workload / project ID in the source system"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/MigrationStep"},"description":"Ordered list of migration steps that will be executed.\n\nThis is the human-readable execution plan. Each step describes what\nwill happen, what risks are involved, and what the user should verify.\nSteps are executed in order. If a step fails, execution stops and\nalready-created resources are reported for manual cleanup."},"summary":{"$ref":"#/components/schemas/MigrationSummary","description":"Human-readable summary of the entire migration"},"version":{"type":"string","description":"Plan version for compatibility tracking"}}},"ImportRowErrorResponse":{"type":"object","required":["row","reason"],"properties":{"reason":{"type":"string"},"row":{"type":"integer","minimum":0}}},"ImportSelector":{"type":"object","description":"Selector for discovering workloads","properties":{"label_filter":{"type":["object","null"],"description":"Filter by labels/tags","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"limit":{"type":["integer","null"],"description":"Limit number of results","minimum":0},"name_pattern":{"type":["string","null"],"description":"Filter by name pattern (glob/regex)"},"status_filter":{"type":["array","null"],"items":{"type":"string"},"description":"Filter by status (running, stopped, deployed, etc.)"},"workload_type_filter":{"type":["array","null"],"items":{"type":"string"},"description":"Filter by workload type (container, function, static-site, etc.)"}}},"ImportSource":{"type":"string","description":"Import source identifier","enum":["docker","coolify","dokploy","vercel","netlify","railway","render","fly","kubernetes","caprover","portainer","kamal","custom"]},"ImportSourceCapabilities":{"type":"object","description":"Source capabilities","required":["supports_volumes","supports_networks","supports_health_checks","supports_resource_limits","supports_build","supports_services","supports_domains","supports_project_snapshot","supports_cost_analysis","requires_credentials"],"properties":{"requires_credentials":{"type":"boolean","description":"Whether this source requires API credentials (token, base URL)"},"supports_build":{"type":"boolean"},"supports_cost_analysis":{"type":"boolean","description":"Supports cluster cost + overprovisioning analysis in the plan"},"supports_domains":{"type":"boolean","description":"Supports custom domain migration"},"supports_health_checks":{"type":"boolean"},"supports_networks":{"type":"boolean"},"supports_project_snapshot":{"type":"boolean","description":"Supports full project-level snapshots"},"supports_resource_limits":{"type":"boolean"},"supports_services":{"type":"boolean","description":"Supports service migration (databases, caches, etc.)"},"supports_volumes":{"type":"boolean"}}},"ImportSourceInfo":{"type":"object","description":"Information about an import source","required":["source","name","version","available","capabilities"],"properties":{"available":{"type":"boolean","description":"Whether the source is currently available"},"capabilities":{"$ref":"#/components/schemas/ImportSourceCapabilities","description":"Capabilities"},"name":{"type":"string","description":"Human-readable name"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source identifier"},"version":{"type":"string","description":"Source version"}}},"ImportStatusResponse":{"type":"object","description":"Response with import status","required":["session_id","status","errors","warnings","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","description":"Created at timestamp"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Created deployment ID"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Created environment ID"},"errors":{"type":"array","items":{"type":"string"},"description":"Errors (if any)"},"plan":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ImportPlan","description":"Import plan"}]},"project_id":{"type":["integer","null"],"format":"int32","description":"Created project ID"},"session_id":{"type":"string","description":"Session ID"},"status":{"$ref":"#/components/schemas/ImportExecutionStatus","description":"Current status"},"updated_at":{"type":"string","format":"date-time","description":"Updated at timestamp"},"validation":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ValidationReport","description":"Validation report"}]},"warnings":{"type":"array","items":{"type":"string"},"description":"Warnings (if any)"}}},"IncidentBucket":{"type":"object","required":["bucket_start","total_incidents","minor_incidents","major_incidents","critical_incidents","resolved_incidents","active_incidents"],"properties":{"active_incidents":{"type":"integer","format":"int64"},"avg_resolution_time_minutes":{"type":["number","null"],"format":"double"},"bucket_start":{"type":"string","format":"date-time"},"critical_incidents":{"type":"integer","format":"int64"},"major_incidents":{"type":"integer","format":"int64"},"minor_incidents":{"type":"integer","format":"int64"},"resolved_incidents":{"type":"integer","format":"int64"},"total_incidents":{"type":"integer","format":"int64"}}},"IncidentBucketedResponse":{"type":"object","required":["project_id","interval","buckets"],"properties":{"buckets":{"type":"array","items":{"$ref":"#/components/schemas/IncidentBucket"}},"environment_id":{"type":["integer","null"],"format":"int32"},"interval":{"type":"string"},"project_id":{"type":"integer","format":"int32"}}},"IncidentResponse":{"type":"object","required":["id","project_id","title","severity","status","started_at","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"monitor_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"format":"date-time"},"severity":{"type":"string"},"started_at":{"type":"string","format":"date-time"},"status":{"type":"string"},"title":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"IncidentUpdateResponse":{"type":"object","required":["id","incident_id","status","message","created_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"integer","format":"int32"},"incident_id":{"type":"integer","format":"int32"},"message":{"type":"string"},"status":{"type":"string"}}},"IncrRequest":{"type":"object","description":"Request to increment a value","required":["key"],"properties":{"amount":{"type":["integer","null"],"format":"int64","description":"Amount to increment by (default: 1)"},"key":{"type":"string","description":"The key to increment","example":"counter"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"IncrResponse":{"type":"object","description":"Response for increment operation","required":["value"],"properties":{"value":{"type":"integer","format":"int64","description":"New value after increment","example":42}}},"InitAuthResponse":{"type":"object","required":["auth_url","session_token"],"properties":{"auth_url":{"type":"string"},"session_token":{"type":"string"}}},"Insight":{"type":"object","description":"An anomaly insight.","required":["id","project_id","service_name","severity","status","title","description","anomaly_ids","started_at","created_at","updated_at"],"properties":{"anomaly_ids":{"type":"array","items":{"type":"integer","format":"int64"}},"correlated_deploy_id":{"type":["integer","null"],"format":"int32"},"created_at":{"type":"string","format":"date-time"},"description":{"type":"string"},"environment":{"type":["string","null"]},"id":{"type":"integer","format":"int64"},"metric_name":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"format":"date-time"},"service_name":{"type":"string"},"severity":{"$ref":"#/components/schemas/InsightSeverity"},"started_at":{"type":"string","format":"date-time"},"status":{"$ref":"#/components/schemas/InsightStatus"},"title":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"InsightSeverity":{"type":"string","description":"Severity of an anomaly insight.","enum":["low","medium","high","critical"]},"InsightStatus":{"type":"string","description":"Status of an insight.","enum":["active","resolved"]},"InsightsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/Insight"}}}},"IntegrationResponse":{"type":"object","required":["id","project_id","provider","webhook_path_token","webhook_path","status","has_secret","created_at"],"properties":{"config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProviderConfig","description":"Typed provider config — allowlist and metered-billing mode. Null\nwhen the operator hasn't configured one yet (accept everything)."}]},"created_at":{"type":"string","format":"date-time"},"has_secret":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"last_event_at":{"type":["string","null"],"format":"date-time"},"project_id":{"type":"integer","format":"int32"},"provider":{"type":"string"},"status":{"type":"string"},"webhook_path":{"type":"string","description":"Relative path the UI can display and copy. The frontend builds\nthe full URL by prefixing its own origin."},"webhook_path_token":{"type":"string","description":"Unguessable token embedded in the public webhook URL. The full\nURL is `{api_origin}/webhooks/revenue/{provider}/{webhook_path_token}`."}}},"IpAccessControlQuery":{"type":"object","description":"Query parameters for listing IP access control rules","properties":{"action":{"type":["string","null"],"description":"Filter by action (\"block\" or \"allow\")"}}},"IpAccessControlResponse":{"type":"object","description":"Response model for IP access control rules","required":["id","ip_address","action","created_at","updated_at"],"properties":{"action":{"type":"string"},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609Z"},"created_by":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":"string"},"reason":{"type":["string","null"]},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609Z"}}},"JobStatusResponse":{"type":"object","description":"Snapshot of a background job. `status` is one of \"running\" | \"exited\"\n| \"failed\"; `exit_code` is populated only when `status == \"exited\"`.","required":["status","stdout","stderr"],"properties":{"exit_code":{"type":["integer","null"],"format":"int32"},"reason":{"type":["string","null"]},"status":{"type":"string"},"stderr":{"type":"string"},"stdout":{"type":"string"}}},"JobSummaryResponse":{"type":"object","description":"Row in the jobs list. Omits stdout/stderr so a noisy dev server doesn't\nbloat the list payload — callers drill into `GET /jobs/{id}` for the\nfull buffer.","required":["id","status","cmd","started_at"],"properties":{"cmd":{"type":"string"},"exit_code":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"reason":{"type":["string","null"]},"started_at":{"type":"string"},"status":{"type":"string"}}},"JoinTokenStatusResponse":{"type":"object","description":"Response for join token status check","required":["has_token"],"properties":{"has_token":{"type":"boolean","description":"Whether a join token has been configured"}}},"JourneyEvent":{"type":"object","description":"A single event in the visitor journey timeline","required":["id","event_type","event_name","occurred_at","is_entry","is_exit","is_bounce"],"properties":{"event_data":{"description":"Custom event properties (for custom events)"},"event_name":{"type":"string","description":"Resolved event name (event_name for custom events, event_type for system events)"},"event_type":{"type":"string","description":"Event type: \"page_view\", \"page_leave\", \"custom\", \"web_vitals\""},"id":{"type":"integer","format":"int64","description":"Event ID"},"is_bounce":{"type":"boolean","description":"Whether this was a bounce"},"is_entry":{"type":"boolean","description":"Whether this is the entry page of the session"},"is_exit":{"type":"boolean","description":"Whether this is the exit page of the session"},"occurred_at":{"type":"string","format":"date-time","description":"When the event occurred"},"page_path":{"type":["string","null"],"description":"Page path where the event happened"},"page_title":{"type":["string","null"],"description":"Page title (if available)"},"referrer":{"type":["string","null"],"description":"Referrer URL for this event"},"scroll_depth":{"type":["integer","null"],"format":"int32","description":"Scroll depth percentage (0-100)"},"session_page_number":{"type":["integer","null"],"format":"int32","description":"Page number within the session (1-indexed)"},"time_on_page":{"type":["integer","null"],"format":"int32","description":"Time spent on page in seconds (computed, not from column)"}}},"JourneySession":{"type":"object","description":"A session within the visitor journey, grouping events","required":["session_id","started_at","duration_seconds","page_views","events_count","is_bounced","is_engaged","events"],"properties":{"channel":{"type":["string","null"],"description":"Traffic source: channel (e.g. \"organic\", \"direct\", \"social\")"},"duration_seconds":{"type":"integer","format":"int64","description":"Session duration in seconds"},"ended_at":{"type":["string","null"],"format":"date-time","description":"When the session ended"},"entry_path":{"type":["string","null"],"description":"Entry page path"},"events":{"type":"array","items":{"$ref":"#/components/schemas/JourneyEvent"},"description":"Events within this session, ordered chronologically"},"events_count":{"type":"integer","format":"int64","description":"Total events in this session"},"exit_path":{"type":["string","null"],"description":"Exit page path"},"is_bounced":{"type":"boolean","description":"Whether the session was a bounce"},"is_engaged":{"type":"boolean","description":"Whether the visitor was engaged (had non-pageview events)"},"page_views":{"type":"integer","format":"int64","description":"Number of page views in this session"},"referrer":{"type":["string","null"],"description":"Traffic source: referrer URL"},"referrer_hostname":{"type":["string","null"],"description":"Traffic source: referrer hostname"},"session_id":{"type":"integer","format":"int32","description":"Session internal ID"},"started_at":{"type":"string","format":"date-time","description":"When the session started"},"utm_campaign":{"type":["string","null"],"description":"UTM campaign parameter"},"utm_medium":{"type":["string","null"],"description":"UTM medium parameter"},"utm_source":{"type":["string","null"],"description":"UTM source parameter"}}},"KeysRequest":{"type":"object","description":"Request to get keys matching a pattern","required":["pattern"],"properties":{"pattern":{"type":"string","description":"Pattern to match (supports * and ? wildcards)","example":"user:*"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"KeysResponse":{"type":"object","description":"Response for keys operation","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"},"description":"List of matching keys","example":["user:1","user:2","user:3"]}}},"KillJobBody":{"type":"object","properties":{"force":{"type":"boolean","description":"When true, sends SIGKILL immediately. Defaults to SIGTERM so the\nprocess gets a chance to flush (mirrors `Command.kill()` in\n`@vercel/sandbox`, which also accepts a signal override)."}},"additionalProperties":false},"KnownAiAgentsResponse":{"type":"object","description":"Response listing every AI agent the detector knows about.","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentDescriptor"}}}},"KvStatusResponse":{"type":"object","description":"Response for KV service status","required":["enabled","healthy"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image being used","example":"gotempsh/redis-walg:8-bookworm"},"enabled":{"type":"boolean","description":"Whether the KV service is enabled"},"healthy":{"type":"boolean","description":"Whether the underlying Redis service is healthy"},"version":{"type":["string","null"],"description":"Service version","example":"7.2"}}},"LemonSqueezyConfig":{"type":"object","properties":{"product_allowlist":{"type":"array","items":{"type":"string"}},"variant_allowlist":{"type":"array","items":{"type":"string"}}}},"LetsEncryptSettings":{"type":"object","properties":{"email":{"type":["string","null"],"default":null},"environment":{"type":"string","default":"production"}}},"LineContext":{"type":"object","description":"Raw surrounding lines for a single match (grep -C style).","required":["before","after"],"properties":{"after":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"},"description":"Lines immediately after the match, oldest-first."},"before":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"},"description":"Lines immediately before the match, oldest-first."}}},"LinkServiceRequest":{"type":"object","required":["project_id"],"properties":{"project_id":{"type":"integer","format":"int32"}}},"ListAgentsResponse":{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentConfigResponse"}},"total":{"type":"integer","minimum":0}}},"ListApiKeysQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"page_size":{"type":["integer","null"],"format":"int64","minimum":0}}},"ListAuditLogsQuery":{"type":"object","description":"Query parameters for listing audit logs.\n\nEvery field is optional — omitting one means \"don't filter on it\". Deriving\n`IntoParams` makes utoipa render them as optional query params with the\ncorrect types; the previous hand-written `params((\"operation_type\", Query,\n…))` tuples defaulted every param to `required: true, type: string`, which\nmisled both API clients and the AI `describe_api`/`call_api` tools into\nthinking all filters were mandatory.","properties":{"from":{"type":["string","null"],"format":"date-time","description":"Start timestamp (milliseconds since epoch)"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of logs to return"},"offset":{"type":["integer","null"],"format":"int32","description":"Number of logs to skip"},"operation_type":{"type":["string","null"],"description":"Filter logs by operation type (omit for all)"},"to":{"type":["string","null"],"format":"date-time","description":"End timestamp (milliseconds since epoch)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter logs by user ID (omit for all users)"}}},"ListBlobsQuery":{"type":"object","description":"Query parameters for listing blobs","properties":{"cursor":{"type":["string","null"],"description":"Continuation token for pagination"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of items to return","example":100},"prefix":{"type":["string","null"],"description":"Prefix to filter by","example":"images/"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"ListBlobsResponse":{"type":"object","description":"Response for listing blobs","required":["blobs","hasMore"],"properties":{"blobs":{"type":"array","items":{"$ref":"#/components/schemas/BlobResponse"},"description":"List of blobs"},"cursor":{"type":["string","null"],"description":"Continuation token for next page"},"hasMore":{"type":"boolean","description":"Whether there are more results","example":false}}},"ListCustomDomainsResponse":{"type":"object","required":["domains","total"],"properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/CustomDomainResponse"}},"total":{"type":"integer","minimum":0}}},"ListDeploymentTokensQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0}}},"ListDomainsResponse":{"type":"object","required":["domains","total","page","page_size"],"properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListEntitiesQuery":{"type":"object","properties":{"limit":{"type":"integer","description":"Maximum number of entities to return","example":100,"minimum":0},"token":{"type":["string","null"],"description":"Continuation token for pagination (backend-specific)"}}},"ListErrorEventsQuery":{"type":"object","properties":{"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0}}},"ListErrorGroupsQuery":{"type":"object","properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"sort_by":{"type":["string","null"]},"sort_order":{"type":"string"},"start_date":{"type":["string","null"],"format":"date-time"},"status":{"type":["string","null"]}}},"ListJobsResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/JobSummaryResponse"}}}},"ListMcpsResponse":{"type":"object","description":"Concrete list wrapper for MCP server definitions (utoipa requires non-generic types).","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/McpDefinitionResponse"}},"total":{"type":"integer","minimum":0}}},"ListOnDemandCertsResponse":{"type":"object","description":"Paginated list of on-demand cert attempts (ADR-018 §5 console \"Certificates\"\nsurface). Joined with current `domains.status`, newest first.","required":["certs","total","page","page_size"],"properties":{"certs":{"type":"array","items":{"$ref":"#/components/schemas/OnDemandCertRow"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListOrdersResponse":{"type":"object","required":["orders"],"properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/AcmeOrderResponse"}}}},"ListPresetsResponse":{"type":"object","required":["presets","total"],"properties":{"presets":{"type":"array","items":{"$ref":"#/components/schemas/PresetResponse"}},"total":{"type":"integer","minimum":0}}},"ListRunsResponse":{"type":"object","required":["items","total","page","page_size"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListSandboxesResponse":{"type":"object","description":"SDK list response: `{ sandboxes: [...], pagination: {...} }`.","required":["sandboxes","pagination"],"properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"sandboxes":{"type":"array","items":{"$ref":"#/components/schemas/SandboxInner"}}}},"ListScansQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0}}},"ListSecretsResponse":{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SecretResponse"}},"total":{"type":"integer","minimum":0}}},"ListSkillsResponse":{"type":"object","description":"Concrete list wrapper for skill definitions (utoipa requires non-generic types).","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SkillDefinitionResponse"}},"total":{"type":"integer","minimum":0}}},"ListTagsResponse":{"type":"object","description":"Response for listing tags","required":["tags","total"],"properties":{"tags":{"type":"array","items":{"type":"string"},"description":"List of available tags"},"total":{"type":"integer","description":"Total number of tags","minimum":0}}},"ListTemplatesQuery":{"type":"object","description":"Query parameters for listing templates","properties":{"featured":{"type":["boolean","null"],"description":"Only return featured templates"},"tag":{"type":["string","null"],"description":"Filter templates by tag"}}},"ListTemplatesResponse":{"type":"object","description":"Response for listing templates","required":["templates","total"],"properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/TemplateResponse"},"description":"List of templates"},"total":{"type":"integer","description":"Total number of templates","minimum":0}}},"ListVulnerabilitiesQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0},"severity":{"type":["string","null"],"example":"CRITICAL"}}},"LiveVisitorInfo":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"current_page":{"type":["string","null"],"description":"Most recent page path visited by this visitor"},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"LiveVisitorsListResponse":{"type":"object","required":["total_count","visitors","window_minutes"],"properties":{"total_count":{"type":"integer","format":"int64"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/LiveVisitorInfo"}},"window_minutes":{"type":"integer","format":"int32"}}},"LocationCount":{"type":"object","required":["location","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"location":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"LocationGranularity":{"type":"string","enum":["country","region","city"]},"LocationInfo":{"type":"object","properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"region":{"type":["string","null"]}}},"LogLevel":{"type":"string","description":"Normalized log level","enum":["TRACE","DEBUG","INFO","WARN","ERROR"]},"LogRecord":{"type":"object","description":"A single log record ready for storage.","required":["project_id","resource","timestamp","observed_timestamp","severity","severity_text","body","attributes"],"properties":{"attributes":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"body":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"observed_timestamp":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"resource":{"$ref":"#/components/schemas/ResourceInfo"},"severity":{"$ref":"#/components/schemas/LogSeverity"},"severity_text":{"type":"string"},"span_id":{"type":["string","null"]},"timestamp":{"type":"string","format":"date-time"},"trace_id":{"type":["string","null"]}}},"LogSearchLine":{"type":"object","description":"A single line in search results","required":["timestamp","level","service","message","chunk_id","line_offset"],"properties":{"chunk_id":{"type":"string"},"container_id":{"type":"string","description":"Container this line came from — lets the UI tag/group lines by container\nin a combined (\"show all\") multi-container view."},"context":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LineContext","description":"Raw surrounding lines (grep -C). `None` unless `context_lines > 0` was\nrequested. Overlapping windows between nearby matches are merged: the\nshared neighbors appear on the earlier match only, so the frontend can\nrender one continuous block without duplicated lines."}]},"deploy_id":{"type":["integer","null"],"format":"int32"},"fields":{},"level":{"$ref":"#/components/schemas/LogLevel"},"line_offset":{"type":"integer","format":"int32"},"message":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Worker node the line came from (`None` = control-plane-local)."},"node_name":{"type":["string","null"],"description":"Human-readable node name for display."},"service":{"type":"string"},"timestamp":{"type":"string"}}},"LogSeverity":{"type":"string","description":"Log severity level (simplified from OTel's 24 levels).","enum":["TRACE","DEBUG","INFO","WARN","ERROR","FATAL"]},"LogSource":{"type":"object","description":"A distinct log source (container) seen in the queried scope. Used to populate\nthe history filter dropdowns with the *full* set of containers/nodes for the\nproject + env + deployment + time window — independent of the active\ncontainer/node/service filter, so the user can switch between them.","required":["container_id","service"],"properties":{"container_id":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32"},"node_name":{"type":["string","null"]},"service":{"type":"string"}}},"LogStream":{"type":"string","description":"Log output stream","enum":["stdout","stderr"]},"LoginRequest":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"}}},"LogsQuery":{"type":"object","properties":{"tail":{"type":["integer","null"],"description":"Number of lines to return from the tail. Defaults to 200, capped at 2000.","minimum":0}}},"LogsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/LogRecord"}}}},"ManagedDomainResponse":{"type":"object","description":"Managed domain response","required":["id","provider_id","domain","auto_manage","verified","generated_hostname_mode","sync_generated_records","created_at","updated_at"],"properties":{"auto_manage":{"type":"boolean"},"created_at":{"type":"string"},"domain":{"type":"string"},"generated_hostname_mode":{"type":"string","description":"Generated hostname layout: `\"standard\"` or `\"flat\"`."},"id":{"type":"integer","format":"int32"},"provider_id":{"type":"integer","format":"int32"},"sync_generated_records":{"type":"boolean","description":"Whether generated hostnames are reconciled into the provider's DNS zone."},"updated_at":{"type":"string"},"verification_error":{"type":["string","null"]},"verified":{"type":"boolean"},"verified_at":{"type":["string","null"]},"zone_access_error":{"type":["string","null"],"description":"Detail for a failed zone-access check."},"zone_access_ok":{"type":["boolean","null"],"description":"Last token zone-access check: `Some(true)`/`Some(false)`/`None` (unchecked)."},"zone_id":{"type":["string","null"]}}},"ManualAction":{"type":"object","description":"A manual action the user must perform outside of the automated migration","required":["timing","description","reason"],"properties":{"description":{"type":"string","description":"Human-readable description"},"reason":{"type":"string","description":"Why this can't be automated"},"timing":{"$ref":"#/components/schemas/ManualActionTiming","description":"When this action needs to happen"}}},"ManualActionTiming":{"type":"string","description":"When a manual action needs to happen relative to migration","enum":["before-migration","after-migration","within-hours"]},"McpDefinitionResponse":{"type":"object","required":["id","slug","name","config","created_at","updated_at"],"properties":{"config":{"type":"object"},"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"MessageContent":{"oneOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/components/schemas/ContentPart"}}]},"MessagePart":{"oneOf":[{"type":"object","required":["text","type"],"properties":{"text":{"type":"string"},"type":{"type":"string","enum":["text"]}}},{"type":"object","required":["tool","type"],"properties":{"tool":{"$ref":"#/components/schemas/ToolInfo"},"type":{"type":"string","enum":["tool"]}}}],"description":"One ordered segment of an assistant turn: a chunk of prose, or a tool\ninvocation. Mirrors the `metadata.parts` persisted by the chat service."},"MessageResponse":{"type":"object","required":["role","content","created_at"],"properties":{"content":{"type":"string"},"created_at":{"type":"string"},"parts":{"type":["array","null"],"items":{"$ref":"#/components/schemas/MessagePart"},"description":"Ordered render segments (text / tool, in the order they occurred) so a\nreloaded chat shows the same interleaving as the live stream. Absent for\nolder messages persisted before parts were tracked; the client then falls\nback to `tools` (rendered first) + `content`."},"role":{"type":"string"},"tools":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ToolInfo"},"description":"Tools the assistant ran on this turn (persisted in message metadata), so\nthe chat replays its tool work after a reload. Absent for plain turns."}}},"MeteredMode":{"type":"string","description":"How to treat metered-billing subscriptions when computing MRR.\n\n* `DeriveFromInvoices` (default): ignore the subscription row's\n `mrr_minor` for metered items and rely on the per-invoice\n [`NormalizedEventType::MrrRealized`] events instead. Correct for\n pure-metered, hybrid, tiered, and flat — recommended.\n* `UseSubscription`: trust whatever MRR the subscription parser\n returns (0 for metered). Legacy behavior.\n* `Ignore`: drop metered subscriptions from MRR entirely.","enum":["derive_from_invoices","use_subscription","ignore"]},"MetricAggregation":{"oneOf":[{"type":"string","description":"Arithmetic mean of the scalar value in each bucket. The default.","enum":["avg"]},{"type":"string","description":"Sum of the scalar value in each bucket.","enum":["sum"]},{"type":"string","description":"Minimum scalar value in each bucket.","enum":["min"]},{"type":"string","description":"Maximum scalar value in each bucket.","enum":["max"]},{"type":"string","description":"Number of points in each bucket.","enum":["count"]},{"type":"string","description":"Per-second rate of change of a cumulative monotonic counter, computed as\n`(max - min) / window_seconds` within each bucket. Non-monotonic series\nfall back to a simple delta.","enum":["rate_per_sec"]},{"type":"object","description":"A quantile of the scalar value in each bucket. The carried `f64` is the\nrequested quantile in `[0.0, 1.0]`.","required":["quantile"],"properties":{"quantile":{"type":"number","format":"double","description":"A quantile of the scalar value in each bucket. The carried `f64` is the\nrequested quantile in `[0.0, 1.0]`."}}}],"description":"The aggregation applied when reducing raw metric points into a time bucket.\n\nStore-neutral: every storage backend (ClickHouse today, TimescaleDB later)\nmust be able to satisfy this contract. `Quantile(q)` carries the requested\nquantile in `[0.0, 1.0]` (e.g. `0.95` for p95)."},"MetricBucket":{"type":"object","description":"A time-bucketed metric aggregate for chart display.\n\nStore-neutral response contract. The legacy scalar fields\n(`avg_value`/`min_value`/`max_value`/`count`) are always populated for chart\nback-compat. The richer fields describe the explicitly-requested\n[`MetricAggregation`] (`value`), optional `quantiles`, an optional\n`histogram_summary`, and a `series_key` identifying the label-set when the\nquery used `group_by`.","required":["bucket","avg_value","min_value","max_value","count"],"properties":{"avg_value":{"type":"number","format":"double"},"bucket":{"type":"string","format":"date-time"},"count":{"type":"integer","format":"int64"},"histogram_summary":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/HistogramSummary","description":"A reduced histogram summary when the bucketed metric is a histogram."}]},"max_value":{"type":"number","format":"double"},"min_value":{"type":"number","format":"double"},"quantiles":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"number","format":"double"},{"type":"number","format":"double"}]},"description":"Computed quantile/value pairs `(quantile, value)` when the query asked for\nquantile aggregation; otherwise empty."},"series_key":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"The label-set this bucket belongs to, as ordered `(key, value)` pairs,\nwhen the query grouped by labels. Empty/`None` = the single ungrouped\naggregate stream."},"value":{"type":"number","format":"double","description":"The value of the requested [`MetricAggregation`] for this bucket. For the\ndefault `Avg` aggregation this equals `avg_value`. `#[serde(default)]` so\npre-existing payloads (which only carried avg/min/max/count) still parse."}}},"MetricDataPoint":{"type":"object","description":"A single `(timestamp, value)` data point in a metric series.","required":["time","value"],"properties":{"time":{"type":"string","description":"ISO 8601 timestamp with `Z` suffix."},"value":{"type":"number","format":"double","description":"Metric value at this bucket."}}},"MetricType":{"type":"string","description":"The type of an OTel metric.","enum":["gauge","sum","histogram","exponential_histogram","summary"]},"MetricsOverTimeResponse":{"type":"object","required":["timestamps","ttfb","lcp","fid","fcp","cls","inp"],"properties":{"cls":{"type":"array","items":{"type":["number","null"],"format":"float"}},"cls_p75":{"type":["number","null"],"format":"float"},"cls_p90":{"type":["number","null"],"format":"float"},"cls_p95":{"type":["number","null"],"format":"float"},"cls_p99":{"type":["number","null"],"format":"float"},"fcp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"fcp_p75":{"type":["number","null"],"format":"float"},"fcp_p90":{"type":["number","null"],"format":"float"},"fcp_p95":{"type":["number","null"],"format":"float"},"fcp_p99":{"type":["number","null"],"format":"float"},"fid":{"type":"array","items":{"type":["number","null"],"format":"float"}},"fid_p75":{"type":["number","null"],"format":"float"},"fid_p90":{"type":["number","null"],"format":"float"},"fid_p95":{"type":["number","null"],"format":"float"},"fid_p99":{"type":["number","null"],"format":"float"},"inp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"inp_p75":{"type":["number","null"],"format":"float"},"inp_p90":{"type":["number","null"],"format":"float"},"inp_p95":{"type":["number","null"],"format":"float"},"inp_p99":{"type":["number","null"],"format":"float"},"lcp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"lcp_p75":{"type":["number","null"],"format":"float"},"lcp_p90":{"type":["number","null"],"format":"float"},"lcp_p95":{"type":["number","null"],"format":"float"},"lcp_p99":{"type":["number","null"],"format":"float"},"timestamps":{"type":"array","items":{"type":"string"}},"ttfb":{"type":"array","items":{"type":["number","null"],"format":"float"}},"ttfb_p75":{"type":["number","null"],"format":"float"},"ttfb_p90":{"type":["number","null"],"format":"float"},"ttfb_p95":{"type":["number","null"],"format":"float"},"ttfb_p99":{"type":["number","null"],"format":"float"}}},"MetricsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"MetricsRangeQuery":{"type":"object","description":"Query params for range metric queries.","required":["metric"],"properties":{"metric":{"type":"string","description":"Metric name, e.g. `\"pg.connections_active\"`."},"percentile":{"type":["number","null"],"format":"double","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile."},"range":{"type":"string","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`."}}},"MetricsStatusResponse":{"type":"object","description":"Freshness status: when metrics were last received for this service.","properties":{"last_received_at":{"type":["string","null"],"description":"ISO 8601 timestamp of the most recent metric row, or null if none yet."}}},"MetricsStoreKind":{"type":"string","description":"Which storage backend to use for the MetricsStore.","enum":["timescale_db","click_house"]},"MetricsSummaryResponse":{"type":"object","required":["currency","current_mrr_minor","current_arr_minor","active_subscriptions","active_customers","churned_last_30d","arpu_minor"],"properties":{"active_customers":{"type":"integer","format":"int64"},"active_subscriptions":{"type":"integer","format":"int64"},"arpu_minor":{"type":"integer","format":"int64"},"churned_last_30d":{"type":"integer","format":"int64"},"currency":{"type":"string"},"current_arr_minor":{"type":"integer","format":"int64"},"current_mrr_minor":{"type":"integer","format":"int64"}}},"MfaRequiredResponse":{"type":"object","required":["requires_mfa","session_token"],"properties":{"requires_mfa":{"type":"boolean"},"session_token":{"type":"string"}}},"MfaSetupResponse":{"type":"object","required":["secret_key","qr_code","recovery_codes"],"properties":{"qr_code":{"type":"string"},"recovery_codes":{"type":"array","items":{"type":"string"}},"secret_key":{"type":"string"}}},"MfaVerificationRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"MigrationStep":{"type":"object","description":"A single step in the migration execution plan.\n\nSteps are presented to the user before execution so they know exactly\nwhat will happen. During execution, each step runs in order and reports\nits outcome before proceeding to the next.","required":["order","id","title","description","resource_type","risk","skippable","reversible"],"properties":{"data_implications":{"type":"array","items":{"$ref":"#/components/schemas/DataImplication"},"description":"Data implications — what could go wrong or what the user needs to know"},"description":{"type":"string","description":"Detailed description of what this step does"},"estimated_duration":{"type":["string","null"],"description":"Estimated duration hint (e.g., \"< 1 second\", \"10-30 seconds\")"},"id":{"type":"string","description":"Machine-readable step identifier (e.g., \"create-project\", \"create-service-postgres\")"},"order":{"type":"integer","description":"Step number (1-based, for display)","minimum":0},"post_conditions":{"type":"array","items":{"type":"string"},"description":"Things the user should verify AFTER this step completes"},"pre_conditions":{"type":"array","items":{"type":"string"},"description":"Things the user should verify BEFORE this step runs"},"resource_type":{"$ref":"#/components/schemas/StepResourceType","description":"What kind of resource this step creates/modifies"},"reversible":{"type":"boolean","description":"Whether this step is reversible (can be cleaned up on failure)"},"risk":{"$ref":"#/components/schemas/RiskLevel","description":"Risk level for this step"},"skippable":{"type":"boolean","description":"Whether this step can be skipped by the user"},"skipped":{"type":"boolean","description":"Whether the user has chosen to skip this step (set during review)"},"title":{"type":"string","description":"Human-readable title (e.g., \"Create project 'my-app'\")"}}},"MigrationSummary":{"type":"object","description":"Human-readable summary of the entire migration plan","required":["headline","overall_risk","resource_counts"],"properties":{"critical_warnings":{"type":"array","items":{"type":"string"},"description":"Critical warnings that must be acknowledged before proceeding.\nThese are the most important things the user needs to know."},"headline":{"type":"string","description":"One-line summary (e.g., \"Migrate 'my-app' from Vercel with 1 database, 2 domains\")"},"manual_actions_required":{"type":"array","items":{"$ref":"#/components/schemas/ManualAction"},"description":"Manual actions the user must perform (before or after migration)"},"overall_risk":{"$ref":"#/components/schemas/RiskLevel","description":"Overall risk assessment for the migration"},"resource_counts":{"$ref":"#/components/schemas/ResourceCounts","description":"Resource counts for quick overview"},"unsupported_features":{"type":"array","items":{"$ref":"#/components/schemas/UnsupportedFeature"},"description":"Features from the source platform that cannot be migrated"}}},"MintEnrollmentTokenRequest":{"type":"object","properties":{"bound_node_name":{"type":["string","null"],"description":"Optional: restrict the token to register one specific node name."},"max_uses":{"type":["integer","null"],"format":"int32","description":"Maximum registrations this token may authorize (default 1)."},"ttl_secs":{"type":["integer","null"],"format":"int64","description":"Time-to-live in seconds (default 3600 = 1h)."}}},"MintEnrollmentTokenResponse":{"type":"object","required":["id","token","expires_at","max_uses","message"],"properties":{"ca_fingerprint":{"type":["string","null"],"description":"SHA-256 fingerprint of the cluster CA (if mTLS is set up). Pass it to the\nworker as `temps join --ca-fingerprint ` to verify the CA on join."},"expires_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"max_uses":{"type":"integer","format":"int32"},"message":{"type":"string"},"token":{"type":"string","description":"The plaintext enrollment token — shown only once, save it now."}}},"MiscResult":{"type":"object","description":"Miscellaneous validation result","required":["is_disposable","is_role_account","is_b2c"],"properties":{"gravatar_url":{"type":["string","null"],"description":"Gravatar URL if available"},"is_b2c":{"type":"boolean","description":"Whether the email provider is a B2C (consumer) email provider"},"is_disposable":{"type":"boolean","description":"Whether the email is from a disposable email provider"},"is_role_account":{"type":"boolean","description":"Whether the email is a role-based account (e.g., admin@, info@)"}}},"MkdirBody":{"type":"object","required":["path"],"properties":{"path":{"type":"string"}},"additionalProperties":false},"ModelInfo":{"type":"object","required":["id","object","owned_by"],"properties":{"id":{"type":"string"},"object":{"type":"string"},"owned_by":{"type":"string"}}},"ModelListResponse":{"type":"object","required":["object","data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ModelInfo"}},"object":{"type":"string"}}},"ModelPricing":{"type":"object","description":"Pricing for a single model, all values in USD per 1M tokens.\nFields are optional because not every provider supports every pricing tier.","required":["model","display_name","provider","input_per_million","output_per_million"],"properties":{"batch_input_per_million":{"type":["number","null"],"format":"double","description":"Batch API input cost per 1M tokens (if provider offers batch pricing)"},"batch_output_per_million":{"type":["number","null"],"format":"double","description":"Batch API output cost per 1M tokens"},"cache_hit_per_million":{"type":["number","null"],"format":"double","description":"Cache hit / refresh cost per 1M tokens"},"cache_write_1h_per_million":{"type":["number","null"],"format":"double","description":"1-hour cache write cost per 1M tokens"},"cache_write_5m_per_million":{"type":["number","null"],"format":"double","description":"5-minute cache write cost per 1M tokens (Anthropic-style prompt caching)"},"deprecated":{"type":"boolean","description":"Whether the model is deprecated"},"display_name":{"type":"string","description":"Human-readable model name (e.g. \"Claude Sonnet 4.6\")"},"input_per_million":{"type":"number","format":"double","description":"Base input token cost per 1M tokens"},"model":{"type":"string","description":"Model identifier (e.g. \"gpt-5.4\", \"claude-sonnet-4-6\")"},"output_per_million":{"type":"number","format":"double","description":"Output token cost per 1M tokens"},"provider":{"type":"string","description":"Provider ID (e.g. \"openai\", \"anthropic\")"}}},"ModelUsage":{"type":"object","required":["model","provider","request_count","input_tokens","output_tokens","total_tokens","avg_latency_ms"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"input_tokens":{"type":"integer","format":"int64"},"model":{"type":"string"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"MonitorResponse":{"type":"object","required":["id","project_id","name","monitor_type","monitor_url","check_interval_seconds","is_active","created_at","updated_at"],"properties":{"check_interval_seconds":{"type":"integer","format":"int32"},"check_path":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"monitor_type":{"type":"string"},"monitor_url":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time"}}},"MonitorStatus":{"type":"object","required":["monitor","current_status","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["integer","null"],"format":"int32"},"current_status":{"type":"string"},"monitor":{"$ref":"#/components/schemas/MonitorResponse"},"uptime_percentage":{"type":"number","format":"double"}}},"MonitoringSettings":{"type":"object","description":"Global metrics observability configuration.\n\nControls whether the MetricsScraper and AlertEvaluator background tasks\nare active, which storage backend they write to, and how long data is kept\nat each retention tier.","properties":{"clickhouse_url":{"type":["string","null"],"description":"ClickHouse DSN (legacy, optional). The runtime metrics store is built\nfrom the `TEMPS_CLICKHOUSE_*` env vars, never from this field; it is\nretained for compatibility and operator reference only.\nExample: `\"http://localhost:8123\"`.","default":null},"enabled":{"type":"boolean","description":"Enable or disable all metrics collection (scraping + alerting).\nDefaults to `false` so new installs don't write to TimescaleDB until\nan operator explicitly enables the feature.","default":false},"retention_daily_years":{"type":"integer","format":"int32","description":"How many years of daily-aggregate data to keep (converted to days internally).","default":2,"example":2,"maximum":10,"minimum":1},"retention_hourly_days":{"type":"integer","format":"int32","description":"How many days of hourly-aggregate data to keep.","default":90,"example":90,"minimum":1},"retention_raw_days":{"type":"integer","format":"int32","description":"How many days of raw (30 s resolution) metric data to keep.","default":7,"example":7,"minimum":1},"scrape_interval_secs":{"type":"integer","format":"int64","description":"How often the MetricsScraper collects data from all sources, in seconds.\nMinimum effective value is 10 s; values below that are clamped at runtime.","default":30,"example":30,"minimum":10},"store":{"oneOf":[{"$ref":"#/components/schemas/MetricsStoreKind","description":"Storage backend for metric data."}],"default":"timescale_db"}}},"MonitoringSettingsMasked":{"type":"object","description":"Monitoring settings with the ClickHouse DSN masked.\n\n`clickhouse_url` can embed credentials (`http://user:pass@host`), so it is\nreported only as a boolean (`clickhouse_url_set`) rather than echoed back —\nconsistent with how the DNS API key and Docker registry password are masked.","required":["enabled","store","scrape_interval_secs","retention_raw_days","retention_hourly_days","retention_daily_years","clickhouse_url_set"],"properties":{"clickhouse_url_set":{"type":"boolean","description":"True when a ClickHouse DSN is configured. The DSN itself is never\nreturned over HTTP because it may contain credentials."},"enabled":{"type":"boolean"},"retention_daily_years":{"type":"integer","format":"int32","minimum":0},"retention_hourly_days":{"type":"integer","format":"int32","minimum":0},"retention_raw_days":{"type":"integer","format":"int32","minimum":0},"scrape_interval_secs":{"type":"integer","format":"int64","minimum":0},"store":{"$ref":"#/components/schemas/MetricsStoreKind"}}},"MrrBucketResponse":{"type":"object","required":["bucket","mrr_minor","charge_total_minor","refund_total_minor","charge_count"],"properties":{"bucket":{"type":"string","format":"date-time"},"charge_count":{"type":"integer","format":"int64"},"charge_total_minor":{"type":"integer","format":"int64"},"mrr_minor":{"type":"integer","format":"int64"},"refund_total_minor":{"type":"integer","format":"int64"}}},"MultiNodeSettings":{"type":"object","description":"Multi-node cluster settings","properties":{"cluster_ca_cert_pem":{"type":["string","null"],"description":"Per-cluster CA certificate (PEM) for multi-node mTLS (ADR-020 WS-2.1).\nPublic — distributed to nodes as the trust root and used by the control\nplane as the root for verifying agent server certs. Minted lazily on the\nfirst CSR-bearing registration.","default":null},"cluster_ca_key_encrypted":{"type":["string","null"],"description":"Per-cluster CA private key, AES-256-GCM ciphertext (EncryptionService).\nSECRET — never returned over HTTP (elided in the masked response).","default":null},"join_token_hash":{"type":["string","null"],"description":"SHA-256 hash of the join token (never store plaintext)","default":null},"legacy_shared_token_enabled":{"type":"boolean","description":"Whether the legacy single shared join token is still accepted for node\nregistration (ADR-020 WS-1.1). Defaults to `true` so existing clusters\nkeep working on upgrade; fresh installs should set it `false` and rely on\nshort-lived, single-use enrollment tokens instead.","default":true},"node_cpu_alert_percent":{"type":["number","null"],"format":"double","description":"CPU-usage percent above which a worker node raises a resource alert\n(ADR-020 / monitoring). `None` disables CPU alerting. Default 90.","default":90.0},"node_disk_alert_percent":{"type":["number","null"],"format":"double","description":"Disk-usage percent above which a worker node raises a resource alert.\n`None` disables disk alerting. Default 90.","default":90.0},"node_memory_alert_percent":{"type":["number","null"],"format":"double","description":"Memory-usage percent above which a worker node raises a resource alert.\n`None` disables memory alerting. Default 90.","default":90.0},"private_address":{"type":["string","null"],"description":"Private/WireGuard IP address of the control plane node.\nUsed by remote worker nodes to reach services (databases, etc.) running on the control plane.\nSet via `--private-address` or `TEMPS_PRIVATE_ADDRESS`.","default":null},"require_mtls":{"type":"boolean","description":"Whether to enforce multi-node mTLS (ADR-020 WS-2.1). When `false`\n(default), the control plane ignores join-time CSRs and nodes keep\nserving plaintext HTTP — zero behavior change. When `true`, the CP signs\nnode CSRs, nodes serve mutual TLS, and every CP→agent call uses the\ncluster client cert. Observe-then-enforce: flip this on only once all\nworkers have re-enrolled with certs.","default":false}}},"MultiNodeSettingsMasked":{"type":"object","description":"Multi-node settings with `join_token_hash` elided.","required":["has_join_token","require_mtls","legacy_shared_token_enabled"],"properties":{"cluster_ca_fingerprint":{"type":["string","null"],"description":"SHA-256 fingerprint of the cluster CA certificate (public — operators can\nverify it out of band; the CA private key is never exposed)."},"has_join_token":{"type":"boolean"},"legacy_shared_token_enabled":{"type":"boolean","description":"Whether the deprecated shared join token is still accepted."},"node_cpu_alert_percent":{"type":["number","null"],"format":"double","description":"Node resource-alert thresholds (percent); `None` = that alert disabled."},"node_disk_alert_percent":{"type":["number","null"],"format":"double"},"node_memory_alert_percent":{"type":["number","null"],"format":"double"},"private_address":{"type":["string","null"]},"require_mtls":{"type":"boolean","description":"Whether control-plane↔agent mutual TLS is enforced."}}},"MxResult":{"type":"object","description":"MX (Mail Exchange) validation result","required":["accepts_mail","records"],"properties":{"accepts_mail":{"type":"boolean","description":"Whether the domain accepts mail"},"error":{"type":["string","null"],"description":"Error message if MX lookup failed"},"records":{"type":"array","items":{"type":"string"},"description":"List of MX records for the domain","example":["alt1.gmail-smtp-in.l.google.com.","gmail-smtp-in.l.google.com."]}}},"NavEntry":{"type":"object","description":"A navigation entry that the plugin contributes to the Temps UI.","required":["label","icon","section","path","order"],"properties":{"icon":{"type":"string","description":"Lucide icon name (e.g., \"puzzle\", \"database\", \"activity\")"},"label":{"type":"string","description":"Display label in the sidebar"},"order":{"type":"integer","format":"int32","description":"Sort order within the section (lower = higher in list)","minimum":0},"path":{"type":"string","description":"Client-side route path (e.g., \"/my-plugin\")"},"section":{"$ref":"#/components/schemas/NavSection","description":"Which sidebar section this entry belongs to"}}},"NavSection":{"type":"string","description":"Where the plugin's nav entry appears in the Temps UI sidebar.","enum":["platform","settings","project"]},"NetworkConfiguration":{"type":"object","description":"Network configuration","required":["mode","dns_servers"],"properties":{"dns_servers":{"type":"array","items":{"type":"string"},"description":"DNS servers"},"hostname":{"type":["string","null"],"description":"Hostname"},"mode":{"$ref":"#/components/schemas/NetworkMode","description":"Network mode"}}},"NetworkMode":{"oneOf":[{"type":"string","enum":["bridge"]},{"type":"string","enum":["host"]},{"type":"string","enum":["none"]},{"type":"object","required":["custom"],"properties":{"custom":{"type":"string"}}}],"description":"Network mode"},"NixpacksPresetConfig":{"type":"object","description":"Configuration for Nixpacks preset\nNixpacks provider and inline build-plan configuration.","properties":{"nixpacksConfig":{"type":["string","null"],"description":"Optional inline nixpacks.toml contents."},"providers":{"type":"array","items":{"$ref":"#/components/schemas/NixpacksProvider"},"description":"Ordered Nixpacks providers. Empty means repository config or auto-detect;\ninclude `...` to combine auto-detection with explicit providers."}}},"NixpacksProvider":{"type":"string","description":"A Nixpacks build provider.\n\n`Auto` serializes as the native Nixpacks `...` marker, which includes the\nprovider detected from the project alongside any explicitly listed\nproviders.","enum":["...","node","python","rust","go","java","php","ruby","deno","elixir","csharp","fsharp","dart","swift","zig","scala","haskell","clojure","crystal","cobol","gleam","lunatic","scheme","static"]},"NodeContainerListResponse":{"type":"object","required":["containers","total"],"properties":{"containers":{"type":"array","items":{"$ref":"#/components/schemas/NodeContainerResponse"}},"total":{"type":"integer","minimum":0}}},"NodeContainerResponse":{"type":"object","description":"A container running on a specific node, enriched with project/environment context.","required":["container_id","container_name","image_name","status","created_at","deployment_id","project_id","project_name","environment_id","environment_name"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"created_at":{"type":"string"},"deployment_id":{"type":"integer","format":"int32"},"environment_id":{"type":"integer","format":"int32"},"environment_name":{"type":"string"},"image_name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"status":{"type":"string"}}},"NodeCostInfo":{"type":"object","description":"One cluster node with capacity and (when priceable) a cost estimate","required":["name","cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"CPU capacity in millicores"},"instance_type":{"type":["string","null"],"description":"Instance type from `node.kubernetes.io/instance-type` (e.g. \"m5.xlarge\")"},"memory_mb":{"type":"integer","format":"int64","description":"Memory capacity in MB"},"monthly_usd":{"type":["number","null"],"format":"double","description":"Estimated on-demand monthly price in USD. `None` when the instance\ntype is unknown or not in the price table."},"name":{"type":"string","description":"Node name"},"region":{"type":["string","null"],"description":"Region from `topology.kubernetes.io/region`"}}},"NodeInfoResponse":{"type":"object","required":["id","name","address","private_address","role","status","labels","capacity","created_at"],"properties":{"address":{"type":"string"},"capacity":{"description":"Resource capacity/usage metrics from the latest heartbeat"},"created_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"labels":{},"last_heartbeat":{"type":["string","null"]},"name":{"type":"string"},"private_address":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"}}},"NodeListResponse":{"type":"object","required":["nodes","total"],"properties":{"nodes":{"type":"array","items":{"$ref":"#/components/schemas/NodeInfoResponse"}},"total":{"type":"integer","minimum":0}}},"NotificationPreferencesResponse":{"type":"object","required":["email_enabled","slack_enabled","batch_similar_notifications","minimum_severity","deployment_failures_enabled","build_errors_enabled","runtime_errors_enabled","error_threshold","error_time_window","ssl_expiration_enabled","ssl_days_before_expiration","domain_expiration_enabled","dns_changes_enabled","backup_failures_enabled","backup_successes_enabled","s3_connection_issues_enabled","retention_policy_violations_enabled","route_downtime_enabled","load_balancer_issues_enabled","weekly_digest_enabled","digest_send_day","digest_send_time","digest_sections"],"properties":{"backup_failures_enabled":{"type":"boolean"},"backup_successes_enabled":{"type":"boolean"},"batch_similar_notifications":{"type":"boolean"},"build_errors_enabled":{"type":"boolean"},"deployment_failures_enabled":{"type":"boolean"},"digest_sections":{"$ref":"#/components/schemas/DigestSections"},"digest_send_day":{"type":"string"},"digest_send_time":{"type":"string"},"dns_changes_enabled":{"type":"boolean"},"domain_expiration_enabled":{"type":"boolean"},"email_enabled":{"type":"boolean"},"error_threshold":{"type":"integer","format":"int32"},"error_time_window":{"type":"integer","format":"int32"},"load_balancer_issues_enabled":{"type":"boolean"},"minimum_severity":{"type":"string"},"retention_policy_violations_enabled":{"type":"boolean"},"route_downtime_enabled":{"type":"boolean"},"runtime_errors_enabled":{"type":"boolean"},"s3_connection_issues_enabled":{"type":"boolean"},"slack_enabled":{"type":"boolean"},"ssl_days_before_expiration":{"type":"integer","format":"int32"},"ssl_expiration_enabled":{"type":"boolean"},"weekly_digest_enabled":{"type":"boolean"}}},"NotificationProviderResponse":{"type":"object","required":["id","name","provider_type","config","enabled","created_at","updated_at"],"properties":{"config":{},"created_at":{"type":"integer","format":"int64"},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"ObservabilityCompressionSettings":{"type":"object","description":"TimescaleDB compression policy configuration for append-only observability\ntables. Values are expressed in hours so operators can choose sub-day\nwindows while keeping the API representation unambiguous.","properties":{"otel_spans_after_hours":{"type":"integer","format":"int32","description":"Compress OpenTelemetry span chunks after this many hours. Defaults to\n24 hours.","default":24,"example":24,"maximum":2160,"minimum":1},"proxy_logs_after_hours":{"type":"integer","format":"int32","description":"Compress proxy-log chunks after this many hours. Defaults to 24 hours.","default":24,"example":24,"maximum":720,"minimum":1}}},"ObservabilityEvent":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/RequestRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["request"]}}}]},{"allOf":[{"$ref":"#/components/schemas/SpanRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["span"]}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/RevenueRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["revenue"]}}}]}],"description":"Discriminated union of every row that can appear in the Observe list.\n\nSerializes to `{ \"type\": \"request\" | \"span\" | ... , ...rest }` so the UI\ncan switch on `event.type` without ambiguity.\n\n**No `Log` variant**: runtime stdout/stderr lines live on a dedicated\nLogs page rather than Observe. Logs are too high-volume to interleave\nwith business signals (requests, errors, revenue) without dominating\nthe timeline, and they have their own retention/storage constraints\n(TimescaleDB hypertable + chunked file/S3 store) that don't compose\nwith the merge service's per-kind LIMIT strategy."},"ObservabilityRetentionSettings":{"type":"object","description":"Retention policy configuration for raw observability tables. Values are in\ndays. The Settings API applies them to TimescaleDB; ClickHouse-backed proxy\nlogs and spans retain their storage-level per-row TTL behavior.","properties":{"otel_logs_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry log events for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"otel_metrics_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry metric points for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"otel_spans_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry spans (traces) for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"proxy_logs_days":{"type":"integer","format":"int32","description":"Retain proxy request logs for this many days.","default":30,"example":30,"maximum":3650,"minimum":1}}},"OidcProviderResponse":{"type":"object","required":["id","name","issuer_url","client_id","client_secret","scopes","jit_provisioning","enabled","template","group_claim","role_claim","default_role","trust_idp_email"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string","description":"Always masked — the secret is never returned after creation."},"default_role":{"type":"string"},"enabled":{"type":"boolean"},"group_claim":{"type":"string"},"id":{"type":"integer","format":"int32"},"issuer_url":{"type":"string"},"jit_provisioning":{"type":"boolean"},"name":{"type":"string"},"role_claim":{"type":"string"},"scopes":{"type":"string"},"template":{"type":"string"},"trust_idp_email":{"type":"boolean","description":"When true, the resolver skips the `email_verified` claim gate\nduring SSO login. Only safe for IdPs where an admin controls\nuser provisioning — see `oidc_providers::Model::trust_idp_email`."}}},"OidcProviderSummary":{"type":"object","required":["slug","name","template"],"properties":{"name":{"type":"string"},"slug":{"type":"string","description":"Stable opaque slug — use this as the path parameter when initiating\nOIDC login (`/auth/oidc/login/{slug}`). The integer database ID is\nintentionally omitted from this public endpoint to prevent provider\nenumeration."},"template":{"type":"string","description":"The template the provider was created from — e.g. `keycloak`,\n`okta`, `auth0`, `google`, `azure-ad`, or `generic`. Surfaced on\nthe public login endpoint so the unauthenticated login page can\nrender the right brand logo on the \"Sign in with X\" button.\nNever sensitive — the template name is part of the provider's\npublic identity, not configuration."}}},"OidcProviderUserResponse":{"type":"object","description":"A user that has logged in via a given OIDC provider. Used by the\nadmin \"Users for provider\" panel — the `oidc_subject` is the\nIdP-side identifier we matched on, useful when diagnosing why a\nuser can or can't log in.","required":["id","name","email","email_verified","mfa_enabled","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-15T14:30:00Z"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"oidc_subject":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time","example":"2024-01-15T14:30:00Z"}}},"OidcProvidersListResponse":{"type":"object","required":["providers"],"properties":{"providers":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderSummary"}}}},"OidcRoleMappingResponse":{"type":"object","required":["id","provider_id","priority","idp_group","role"],"properties":{"id":{"type":"integer","format":"int32"},"idp_group":{"type":"string"},"priority":{"type":"integer","format":"int32"},"provider_id":{"type":"integer","format":"int32"},"role":{"type":"string"}}},"OidcTestConnectionResponse":{"type":"object","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"OnDemandCertAttemptResponse":{"type":"object","description":"A single on-demand HTTP-01 issuance attempt from the append-only\n`on_demand_cert_attempts` audit log. Carries the full forensic detail for one\nattempt; the current cert state lives on the enclosing row's domain fields.\n\nContains no private-key or certificate material — only audit metadata — so it\nis safe to return without masking.","required":["id","hostname","trigger","outcome","created_at"],"properties":{"acme_request_sent":{"type":["boolean","null"],"description":"Did we reach the Let's Encrypt API?"},"acme_response_status":{"type":["string","null"],"description":"HTTP status or ACME error type returned by Let's Encrypt, when known."},"challenge_served":{"type":["boolean","null"],"description":"Did the proxy serve the `/.well-known/acme-challenge/` request?"},"created_at":{"type":"integer","format":"int64","description":"When the attempt was recorded (epoch millis)."},"duration_ms":{"type":["integer","null"],"format":"int32","description":"End-to-end issuance duration in milliseconds (0/None for skipped)."},"error_category":{"type":["string","null"],"description":"Coarse error category for UI labelling: `\"rate_limited\"`, `\"dns_failure\"`,\n`\"acme_order_expired\"`, `\"challenge_mismatch\"`, `\"timeout\"`, `\"internal\"`."},"error_chain":{"type":["string","null"],"description":"Full `Display` chain of the error (all `source()` levels), when failed."},"hostname":{"type":"string","description":"SNI hostname that triggered the attempt."},"id":{"type":"integer","format":"int32"},"outcome":{"type":"string","description":"Final outcome: `\"issued\"`, `\"failed\"`, `\"skipped_duplicate\"`,\n`\"skipped_gate\"`, `\"skipped_rate_limit\"`, or `\"skipped_no_route\"`."},"trigger":{"type":"string","description":"What triggered the attempt (always `\"tls_callback\"` today)."}}},"OnDemandCertRow":{"type":"object","description":"One row of the on-demand certificates list: the most-recent attempt for a\nhostname plus the current authoritative cert state from its `domains` row.","required":["hostname","attempt"],"properties":{"attempt":{"$ref":"#/components/schemas/OnDemandCertAttemptResponse","description":"The audit record for the attempt this row represents (newest first in\nthe list)."},"backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand negative-cache deadline (epoch millis), when in backoff."},"expiration_time":{"type":["integer","null"],"format":"int64","description":"Certificate expiration (epoch millis), when an active cert exists."},"hostname":{"type":"string","description":"SNI hostname."},"status":{"type":["string","null"],"description":"Current cert lifecycle status from the `domains` row, when one exists:\n`on_demand_pending`, `on_demand_issuing`, `active`, `on_demand_failed`,\netc. `None` when no `domains` row exists yet for this hostname."}}},"OnDemandTlsSettings":{"type":"object","description":"On-demand (lazy) HTTP-01 TLS issuance settings (ADR-018).\n\nWhen `enabled`, the proxy's `certificate_callback` triggers ACME HTTP-01\nissuance for allowlisted, STABLE hostnames (per-environment aliases and the\nconsole host) that have no active cert, rather than silently failing the\nhandshake. Ephemeral per-deployment hostnames are NEVER certed (ADR §2).\n\nOff by default — operators opt in explicitly, except QuickStart (`sslip.io`)\ninstalls where `temps setup` auto-enables it and derives `zone`.","properties":{"deployment_url_mode":{"type":"string","description":"How ephemeral per-deployment hostnames behave when they have no cert\n(they are NEVER certed — see ADR §2). One of:\n - `\"http\"` (default): serve plain HTTP on :80.\n - `\"redirect_to_env\"`: 308-redirect to the stable per-environment URL,\n which IS certed.","default":"http","example":"http"},"enabled":{"type":"boolean","description":"Master switch. When `false` (default) the proxy's on-demand cert gate\nrejects every SNI and no issuance is ever triggered.","default":false,"example":false},"hourly_cap":{"type":"integer","format":"int32","description":"Global cap on total on-demand issuances per hour across all hostnames\n(ADR §4 Layer 3). The operator's self-imposed safety net, separate from\nthe Let's Encrypt rate limit.","default":10,"example":10,"minimum":1},"max_concurrent":{"type":"integer","format":"int32","description":"Maximum number of ACME issuance flows allowed to run simultaneously\n(the concurrent-issuance semaphore, ADR §4 Layer 1). Min 1.","default":3,"example":3,"minimum":1},"zone":{"type":["string","null"],"description":"Zone suffix for the allowlist gate. A hostname passes the gate only if\nit is a direct subdomain of this zone (e.g. zone `1.2.3.4.sslip.io`\nadmits `myapp.1.2.3.4.sslip.io` but not `deep.sub.1.2.3.4.sslip.io`).\n`None` (default) means \"auto-derive from `external_url`\"; if no zone can\nbe derived the gate rejects all SNI, disabling the feature.","default":null,"example":"1.2.3.4.sslip.io"}}},"OpenAiError":{"type":"object","required":["message","type"],"properties":{"code":{"type":["string","null"]},"message":{"type":"string"},"type":{"type":"string"}}},"OpenAiErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/OpenAiError"}}},"OperatingSystemCount":{"type":"object","required":["operating_system","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"operating_system":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"OperationResultResponse":{"type":"object","required":["operation","success","message","executed_at"],"properties":{"data":{},"executed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"message":{"type":"string"},"operation":{"type":"string"},"success":{"type":"boolean"}}},"OperationResultsResponse":{"type":"object","required":["deployment_id","operations"],"properties":{"deployment_id":{"type":"string"},"operations":{"type":"array","items":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"OtelDashboardResponse":{"type":"object","required":["id","project_id","name","layout","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"id":{"type":"integer","format":"int32"},"layout":{"$ref":"#/components/schemas/DashboardLayout"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"}}},"OtelDashboardsResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OtelDashboardResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"OtelMetricAlertRuleResponse":{"type":"object","required":["id","project_id","name","metric_name","aggregation","detection_kind","detection_config","window_secs","for_duration_secs","severity","enabled","last_state","label_filters","group_by","dynamic_alerts","max_series","grouped_notification_threshold","last_dropped_series_count","series_states","created_at","updated_at"],"properties":{"aggregation":{"type":"string"},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"The typed detector definition (discriminated union keyed by `kind`)."},"detection_kind":{"type":"string","description":"Coarse detector discriminator: `static|anomaly|forecast|outlier|auto_watch`."},"dynamic_alerts":{"type":"boolean","description":"Whether per-series (\"dynamic\") alerting is enabled for this rule."},"enabled":{"type":"boolean"},"firing_series":{"type":"array","items":{"$ref":"#/components/schemas/FiringSeriesEntry"},"description":"Currently-firing series for a dynamic rule, snapshotted from the evaluator's\nin-memory firing map at read time. Empty for static/aggregate rules or when\nnothing is firing."},"for_duration_secs":{"type":"integer","format":"int32"},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys the rule breaks the metric down by. Empty = one aggregate stream."},"grouped_notification_threshold":{"type":"integer","format":"int32","description":"Notification-grouping threshold: when more than this many series fire in the\nsame tick, only the first gets chart/AI enrichment (1–1000)."},"id":{"type":"integer","format":"int32"},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters applied when evaluating this rule.\nEmpty = no filtering (matches all series)."},"last_dropped_series_count":{"type":"integer","format":"int32","description":"Number of series dropped by the cardinality cap on the latest dynamic tick\n(0 when nothing was dropped or for static/aggregate rules). Lets a UI warn\n\"N series were dropped this tick\" without reading server logs."},"last_evaluated_at":{"type":["string","null"],"example":"2025-10-12T12:15:47.609192Z"},"last_state":{"type":"string","description":"One of `ok|firing|unknown`."},"last_value":{"type":["number","null"],"format":"double"},"max_series":{"type":"integer","format":"int32","description":"Cardinality cap for dynamic alerting (1–100)."},"metric_name":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"series_states":{"type":"object","description":"Full per-series state snapshot persisted after the latest dynamic-rule tick,\nkeyed by the human-readable series label (`endpoint=/checkout`). Empty for\nstatic/aggregate rules. Unlike `firing_series` (a live in-memory snapshot),\nthis is decoded from the persisted `series_states` jsonb column, so an\nexternal consumer that only reads the rule row still sees per-series detail.","additionalProperties":{"$ref":"#/components/schemas/SeriesStateEntry"},"propertyNames":{"type":"string"}},"severity":{"type":"string"},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"window_secs":{"type":"integer","format":"int32"}}},"OtelMetricAlertsResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"OtelMetricLabelKeysResponse":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"}}}},"OtelMetricLabelValuesResponse":{"type":"object","required":["values"],"properties":{"values":{"type":"array","items":{"type":"string"}}}},"OtelMetricNamesResponse":{"type":"object","required":["names"],"properties":{"names":{"type":"array","items":{"type":"string"}}}},"OtelMetricsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/MetricBucket"}}}},"OutlierAlgorithm":{"type":"string","description":"Outlier detection algorithm.","enum":["dbscan","scaled_dbscan","mad","scaled_mad"]},"OutlierParams":{"type":"object","description":"Outlier (cross-series population) detector parameters (stub — not evaluated).","required":["peer_group_key"],"properties":{"algorithm":{"$ref":"#/components/schemas/OutlierAlgorithm"},"peer_group_key":{"type":"string","description":"Label key defining the peer population compared across series (e.g. `host`)."},"tolerance":{"type":"number","format":"double","description":"Sensitivity; higher tolerates larger spread before flagging."}}},"OverprovisioningAssessment":{"type":"object","description":"Requests-vs-capacity-vs-usage assessment","required":["verdict","explanation"],"properties":{"cpu_request_inflation_ratio":{"type":["number","null"],"format":"double","description":"Ratio of requested CPU to measured CPU usage (e.g. 40.0 = requests\nreserve 40× what the workloads actually use). `None` without metrics."},"cpu_requested_pct":{"type":["number","null"],"format":"double","description":"Requested CPU as % of cluster capacity"},"cpu_utilization_pct":{"type":["number","null"],"format":"double","description":"Measured CPU usage as % of cluster capacity (`None` without metrics)"},"explanation":{"type":"string","description":"Human-readable explanation of the verdict, e.g. \"Cluster capacity is\n8 vCPU but measured usage is 0.3 vCPU (3.7%) — severely overprovisioned\""},"memory_request_inflation_ratio":{"type":["number","null"],"format":"double","description":"Ratio of requested memory to measured memory usage"},"memory_requested_pct":{"type":["number","null"],"format":"double","description":"Requested memory as % of cluster capacity"},"memory_utilization_pct":{"type":["number","null"],"format":"double","description":"Measured memory usage as % of cluster capacity (`None` without metrics)"},"verdict":{"$ref":"#/components/schemas/OverprovisioningVerdict","description":"Overall verdict"}}},"OverprovisioningVerdict":{"type":"string","description":"Overall overprovisioning verdict","enum":["severe","moderate","reasonable","unknown"]},"PageActivityBucket":{"type":"object","description":"Time bucket data point for page activity graph","required":["timestamp","visitors","page_views","avg_time_seconds"],"properties":{"avg_time_seconds":{"type":"number","format":"double","description":"Average time on page in seconds"},"page_views":{"type":"integer","format":"int64","description":"Number of page views in this bucket"},"timestamp":{"type":"string","description":"Timestamp for this bucket (ISO 8601)"},"visitors":{"type":"integer","format":"int64","description":"Number of unique visitors in this bucket"}}},"PageCountryStats":{"type":"object","description":"Geographic distribution of visitors for a page","required":["country","visitors","page_views","percentage"],"properties":{"country":{"type":"string","description":"Country name"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"page_views":{"type":"integer","format":"int64","description":"Number of page views from this country"},"percentage":{"type":"number","format":"double","description":"Percentage of total visitors"},"visitors":{"type":"integer","format":"int64","description":"Number of unique visitors from this country"}}},"PageFlowEntry":{"type":"object","description":"A single page with its entry/exit/bounce statistics","required":["page_path","entry_count","exit_count","bounce_count","total_views","entry_rate","exit_rate","bounce_rate"],"properties":{"avg_time_on_page":{"type":["number","null"],"format":"double","description":"Average time spent on this page in seconds"},"bounce_count":{"type":"integer","format":"int64","description":"Number of times visitors bounced on this page"},"bounce_rate":{"type":"number","format":"double","description":"Bounce rate: bounce_count / entry_count (only meaningful for entry pages)"},"entry_count":{"type":"integer","format":"int64","description":"Number of times this page was the entry page of a session"},"entry_rate":{"type":"number","format":"double","description":"Entry rate: entry_count / total_views"},"exit_count":{"type":"integer","format":"int64","description":"Number of times this page was the exit page of a session"},"exit_rate":{"type":"number","format":"double","description":"Exit rate: exit_count / total_views"},"page_path":{"type":"string","description":"The page path (e.g. \"/pricing\", \"/docs/getting-started\")"},"total_views":{"type":"integer","format":"int64","description":"Total page views for this page"}}},"PageFlowQuery":{"type":"object","description":"Query parameters for page flow analytics","required":["project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of entry/exit pages to return (default: 20)"},"min_views_for_dropoff":{"type":["integer","null"],"format":"int32","description":"Minimum views for drop-off analysis (default: 5)"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"},"transitions_limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of transitions to return (default: 50)"}}},"PageFlowResponse":{"type":"object","description":"Complete page flow analytics response","required":["top_entry_pages","top_exit_pages","drop_off_points","transitions","total_pages","total_sessions"],"properties":{"drop_off_points":{"type":"array","items":{"$ref":"#/components/schemas/DropOffPoint"},"description":"Top drop-off points (highest exit rates with meaningful traffic)"},"top_entry_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageFlowEntry"},"description":"Top entry pages (where visitors land), sorted by entry_count DESC"},"top_exit_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageFlowEntry"},"description":"Top exit pages (where visitors leave), sorted by exit_count DESC"},"total_pages":{"type":"integer","format":"int64","description":"Total unique pages seen in the period"},"total_sessions":{"type":"integer","format":"int64","description":"Total sessions in the period"},"transitions":{"type":"array","items":{"$ref":"#/components/schemas/PageTransition"},"description":"Page-to-page transitions (most common navigation paths)"}}},"PageHourlySessionsQuery":{"type":"object","description":"Query parameters for page hourly sessions endpoint","required":["page_path","project_id","start_time","end_time"],"properties":{"bucket_interval":{"type":["string","null"]},"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"PageHourlySessionsResponse":{"type":"object","required":["page_path","hourly_data","total_sessions","hours"],"properties":{"hourly_data":{"type":"array","items":{"$ref":"#/components/schemas/HourlyPageSessions"}},"hours":{"type":"integer","format":"int32"},"page_path":{"type":"string"},"total_sessions":{"type":"integer","format":"int64"}}},"PagePathDetailQuery":{"type":"object","description":"Query parameters for page path detail analytics","required":["page_path","project_id","start_date","end_date"],"properties":{"bucket_interval":{"type":["string","null"],"description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string","description":"The specific page path to get details for (URL-encoded)"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PagePathDetailResponse":{"type":"object","description":"Detailed analytics response for a specific page path","required":["page_path","unique_visitors","total_page_views","avg_time_on_page","bounce_rate","entry_rate","exit_rate","activity_over_time","countries","referrers","bucket_interval"],"properties":{"activity_over_time":{"type":"array","items":{"$ref":"#/components/schemas/PageActivityBucket"},"description":"Time series data for activity graph"},"avg_time_on_page":{"type":"number","format":"double","description":"Average time on page in seconds"},"bounce_rate":{"type":"number","format":"double","description":"Bounce rate percentage (0-100)"},"bucket_interval":{"type":"string","description":"Bucket interval used for time series ('hour', 'day', etc.)"},"countries":{"type":"array","items":{"$ref":"#/components/schemas/PageCountryStats"},"description":"Geographic distribution of visitors"},"entry_rate":{"type":"number","format":"double","description":"Entry rate - percentage of sessions that started on this page"},"exit_rate":{"type":"number","format":"double","description":"Exit rate - percentage of sessions that ended on this page"},"page_path":{"type":"string","description":"The page path being analyzed"},"referrers":{"type":"array","items":{"$ref":"#/components/schemas/PageReferrerStats"},"description":"Top referrers to this page"},"total_page_views":{"type":"integer","format":"int64","description":"Total page views in the date range"},"unique_visitors":{"type":"integer","format":"int64","description":"Total unique visitors to this page in the date range"}}},"PagePathInfo":{"type":"object","required":["page_path","session_count","page_view_count","first_seen","last_seen"],"properties":{"avg_time_seconds":{"type":["number","null"],"format":"double"},"first_seen":{"type":"string"},"last_seen":{"type":"string"},"page_path":{"type":"string"},"page_view_count":{"type":"integer","format":"int64"},"session_count":{"type":"integer","format":"int64"}}},"PagePathSparkline":{"type":"object","required":["page_path","points"],"properties":{"page_path":{"type":"string"},"points":{"type":"array","items":{"$ref":"#/components/schemas/PagePathSparklinePoint"}}}},"PagePathSparklinePoint":{"type":"object","required":["timestamp","session_count"],"properties":{"session_count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"PagePathVisitorsQuery":{"type":"object","description":"Query parameters for page path visitors","required":["page_path","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"page_path":{"type":"string","description":"The specific page path to get visitors for"},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 50, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PagePathVisitorsResponse":{"type":"object","description":"Response for page path visitors endpoint","required":["page_path","total_count","page","per_page","sessions"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"page_path":{"type":"string","description":"The page path"},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/PageVisitorSession"},"description":"Individual visitor sessions"},"total_count":{"type":"integer","format":"int64","description":"Total number of visitor sessions matching the query"}}},"PagePathsQuery":{"type":"object","required":["project_id"],"properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":["string","null"],"format":"date-time"}}},"PagePathsResponse":{"type":"object","required":["page_paths","total_count"],"properties":{"page_paths":{"type":"array","items":{"$ref":"#/components/schemas/PagePathInfo"}},"total_count":{"type":"integer","minimum":0}}},"PagePathsSparklineQuery":{"type":"object","description":"Query parameters for batch page paths sparkline endpoint","required":["project_id","start_time","end_time","page_paths"],"properties":{"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_paths":{"type":"string","description":"Comma-separated list of page paths"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"PagePathsSparklineResponse":{"type":"object","required":["sparklines"],"properties":{"sparklines":{"type":"array","items":{"$ref":"#/components/schemas/PagePathSparkline"}}}},"PageReferrerStats":{"type":"object","description":"Referrer source for the page","required":["referrer","visits","percentage"],"properties":{"percentage":{"type":"number","format":"double","description":"Percentage of total visits"},"referrer":{"type":"string","description":"Referrer URL or domain"},"visits":{"type":"integer","format":"int64","description":"Number of visits from this referrer"}}},"PageSessionComparison":{"type":"object","required":["page_path","date","session_count","event_count","avg_duration_seconds"],"properties":{"avg_duration_seconds":{"type":"number","format":"double"},"date":{"type":"string"},"event_count":{"type":"integer","format":"int64"},"page_path":{"type":"string"},"session_count":{"type":"integer","format":"int64"}}},"PageSessionStats":{"type":"object","required":["page_path","total_sessions","avg_time_seconds","min_time_seconds","max_time_seconds","total_page_views","avg_page_views_per_session"],"properties":{"avg_page_views_per_session":{"type":"number","format":"double"},"avg_time_seconds":{"type":"number","format":"double"},"max_time_seconds":{"type":"number","format":"double"},"min_time_seconds":{"type":"number","format":"double"},"page_path":{"type":"string"},"total_page_views":{"type":"integer","format":"int64"},"total_sessions":{"type":"integer","format":"int64"}}},"PageSessionStatsQuery":{"type":"object","required":["page_path","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PageTransition":{"type":"object","description":"A page-to-page transition with count","required":["from_page","to_page","transition_count","percentage"],"properties":{"from_page":{"type":"string","description":"The source page path"},"percentage":{"type":"number","format":"double","description":"Percentage of transitions from the source page that go to this destination"},"to_page":{"type":"string","description":"The destination page path"},"transition_count":{"type":"integer","format":"int64","description":"Number of times this transition occurred"}}},"PageVisit":{"type":"object","required":["path","visits"],"properties":{"path":{"type":"string"},"visits":{"type":"integer","format":"int64"}}},"PageVisitorSession":{"type":"object","description":"Individual visitor session that viewed a specific page","required":["visitor_id","visitor_uuid","viewed_at","is_entry","is_exit","is_bounce"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"Visitor's city"},"country":{"type":["string","null"],"description":"Visitor's country"},"country_code":{"type":["string","null"],"description":"Visitor's country code"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"is_bounce":{"type":"boolean","description":"Whether this was a bounce"},"is_entry":{"type":"boolean","description":"Whether this was the entry page for the session"},"is_exit":{"type":"boolean","description":"Whether this was the exit page for the session"},"operating_system":{"type":["string","null"],"description":"Operating system"},"referrer":{"type":["string","null"],"description":"Referrer URL"},"session_id":{"type":["string","null"],"description":"Session ID"},"session_page_number":{"type":["integer","null"],"format":"int32","description":"Page number in session flow"},"time_on_page":{"type":["integer","null"],"format":"int32","description":"Time spent on this page in seconds"},"viewed_at":{"type":"string","format":"date-time","description":"When the page was viewed"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor numeric ID"},"visitor_uuid":{"type":"string","description":"Visitor UUID"}}},"PagesComparisonResponse":{"type":"object","required":["comparisons","page_paths"],"properties":{"comparisons":{"type":"array","items":{"$ref":"#/components/schemas/PageSessionComparison"}},"page_paths":{"type":"array","items":{"type":"string"}}}},"PaginatedEmailsResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedEntitiesResponse":{"type":"object","required":["entities","count","limit","has_more"],"properties":{"count":{"type":"integer","description":"Number of entities returned","minimum":0},"entities":{"type":"array","items":{"$ref":"#/components/schemas/EntityResponse"},"description":"List of entities"},"has_more":{"type":"boolean","description":"Whether there are more entities available"},"limit":{"type":"integer","description":"Limit used for this request","minimum":0},"next_token":{"type":["string","null"],"description":"Continuation token for next page (S3, etc.)"},"total":{"type":["integer","null"],"description":"Total number of entities (if available)","minimum":0}}},"PaginatedErrorEventsResponse":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ErrorEventResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationMeta"}}},"PaginatedErrorGroupsResponse":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ErrorGroupResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationMeta"}}},"PaginatedEventsResponse":{"type":"object","required":["events","total","page","page_size"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/TrackingEventResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedExternalImagesResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExternalImageResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedProjectList":{"type":"object","required":["projects","total","page","per_page"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"projects":{"type":"array","items":{"$ref":"#/components/schemas/ProjectResponse"}},"total":{"type":"integer","format":"int64"}}},"PaginatedStaticBundlesResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StaticBundleResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"Pagination":{"type":"object","description":"SDK pagination cursor. We use opaque page numbers internally but\nexpose `count`/`next`/`prev` the way `@vercel/sandbox` expects.","required":["count"],"properties":{"count":{"type":"integer","format":"int64","minimum":0},"next":{"type":["integer","null"],"format":"int64","minimum":0},"prev":{"type":["integer","null"],"format":"int64","minimum":0}}},"PaginationMeta":{"type":"object","required":["page","page_size","total_count","total_pages"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total_count":{"type":"integer","format":"int64","minimum":0},"total_pages":{"type":"integer","format":"int64","minimum":0}}},"PaginationParams":{"type":"object","properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"}}},"PasswordProtectionConfig":{"type":"object","description":"Password protection configuration\n\nWhen enabled, the proxy shows an HTML password form before allowing access.\nAfter the user enters the correct password, an HMAC-signed cookie is set\nso subsequent requests pass through without re-entering the password.","required":["enabled","passwordHash"],"properties":{"enabled":{"type":"boolean","description":"Whether password protection is enabled"},"passwordHash":{"type":"string","description":"The bcrypt-hashed password (never stored or returned in plaintext)"}}},"PatchSettingsRequest":{"type":"object","properties":{"auto_upgrade":{"type":["boolean","null"]},"host_port":{"type":["integer","null"],"format":"int32","minimum":0},"image":{"type":["string","null"]}}},"PathVisitors":{"type":"object","required":["name","visitors","percentage"],"properties":{"name":{"type":"string"},"percentage":{"type":"number","format":"double"},"visitors":{"type":"integer","format":"int64"}}},"PathVisitorsAnalyticsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PathVisitorsResponse":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PathVisitors"}}}},"PeerEntry":{"type":"object","description":"Wire-format peer entry. Matches `temps_network::config::Peer` but\nuses strings on the wire to keep the API stable across underlying\ntype evolution.","required":["node_id","compute_cidr","underlay_address"],"properties":{"compute_cidr":{"type":"string","description":"Per-node CIDR (e.g. `\"172.20.5.0/24\"`)."},"node_id":{"type":"string","description":"Stable v5 UUID derived from the database node id. Workers use\nthis as the kernel-layer identifier when calling\n`NetworkManager::reconcile_peers`."},"underlay_address":{"type":"string","description":"Address the local node should use to reach this peer over the\nunderlay (private VPC IP for same-DC, public IP for cross-DC)."}}},"PeerListResponse":{"type":"object","description":"Response body for `GET /internal/nodes/{node_id}/network/peers`.","required":["peers","cluster_dns_enabled"],"properties":{"alloc":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AllocEntry","description":"Caller's own allocation, or `null` if multi-host networking has\nnot been enabled for this node yet."}]},"cluster_dns_enabled":{"type":"boolean","description":"Whether the cluster-DNS resolver is enabled on this control plane\n(`AppSettings.cluster_dns.enabled`). Workers should start their\nper-node resolver and write `overlay_bridge_address` only when this\nis `true`. Always serialized (never `skip_serializing_if`) so older\nand newer version skew degrades to the safe default of `false`."},"peers":{"type":"array","items":{"$ref":"#/components/schemas/PeerEntry"},"description":"All other nodes with a `compute_cidr` set, excluding the caller."}}},"PendingActionResponse":{"type":"object","description":"A proposed AI write action awaiting human confirmation.","required":["public_id","operation_id","method","summary","status","step_index","params","created_at"],"properties":{"confirmed_at":{"type":["string","null"]},"created_at":{"type":"string"},"error":{"type":["string","null"]},"executed_at":{"type":["string","null"]},"method":{"type":"string"},"operation_id":{"type":"string"},"params":{"description":"The flat params to be replayed at execute time (shown pre-execution for review)."},"plan_public_id":{"type":["string","null"],"description":"Set when this action is one step of a multi-step plan (chained actions);\nall steps of the plan share this id. Absent for standalone single actions."},"public_id":{"type":"string"},"required_permission":{"type":["string","null"]},"result":{},"status":{"type":"string"},"step_index":{"type":"integer","format":"int32","description":"0-based order of this step within its plan (0 for standalone actions)."},"summary":{"type":"string"}}},"PerformanceMetricsQuery":{"allOf":[{"$ref":"#/components/schemas/SpeedSegmentFilters","description":"Segment filters (filter_path, filter_country, filter_region,\nfilter_city, filter_browser, filter_operating_system) — flattened so\neach remains a top-level query string param."},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"],"description":"Device type filter: \"desktop\" or \"mobile\""},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"include_bots":{"type":["boolean","null"],"description":"Include crawler/datacenter (bot) samples. Defaults to false — bots\nare excluded from the read view but always stored at ingest."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"PerformanceMetricsResponse":{"type":"object","properties":{"cls":{"type":["number","null"],"format":"float"},"cls_p75":{"type":["number","null"],"format":"float"},"cls_p90":{"type":["number","null"],"format":"float"},"cls_p95":{"type":["number","null"],"format":"float"},"cls_p99":{"type":["number","null"],"format":"float"},"fcp":{"type":["number","null"],"format":"float"},"fcp_p75":{"type":["number","null"],"format":"float"},"fcp_p90":{"type":["number","null"],"format":"float"},"fcp_p95":{"type":["number","null"],"format":"float"},"fcp_p99":{"type":["number","null"],"format":"float"},"fid":{"type":["number","null"],"format":"float"},"fid_p75":{"type":["number","null"],"format":"float"},"fid_p90":{"type":["number","null"],"format":"float"},"fid_p95":{"type":["number","null"],"format":"float"},"fid_p99":{"type":["number","null"],"format":"float"},"inp":{"type":["number","null"],"format":"float"},"inp_p75":{"type":["number","null"],"format":"float"},"inp_p90":{"type":["number","null"],"format":"float"},"inp_p95":{"type":["number","null"],"format":"float"},"inp_p99":{"type":["number","null"],"format":"float"},"lcp":{"type":["number","null"],"format":"float"},"lcp_p75":{"type":["number","null"],"format":"float"},"lcp_p90":{"type":["number","null"],"format":"float"},"lcp_p95":{"type":["number","null"],"format":"float"},"lcp_p99":{"type":["number","null"],"format":"float"},"ttfb":{"type":["number","null"],"format":"float"},"ttfb_p75":{"type":["number","null"],"format":"float"},"ttfb_p90":{"type":["number","null"],"format":"float"},"ttfb_p95":{"type":["number","null"],"format":"float"},"ttfb_p99":{"type":["number","null"],"format":"float"}}},"PermissionInfo":{"type":"object","description":"Information about a single permission","required":["name","description","category"],"properties":{"category":{"type":"string","description":"Category of the permission (e.g., \"Projects\", \"Deployments\")"},"description":{"type":"string","description":"Human-readable description of the permission"},"name":{"type":"string","description":"The permission identifier (e.g., \"projects:read\")"}}},"PgUpgradeLogResponse":{"type":"object","required":["log_id","content"],"properties":{"content":{"type":"string"},"log_id":{"type":"string"}}},"PgUpgradeResponse":{"type":"object","required":["id","service_id","from_version","to_version","from_image","to_image","status","phase","log_id","attempt","created_at"],"properties":{"attempt":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"finished_at":{"type":["string","null"]},"from_image":{"type":"string"},"from_version":{"type":"string"},"id":{"type":"integer","format":"int32"},"log_id":{"type":"string"},"phase":{"type":"string"},"pre_upgrade_backup_id":{"type":["integer","null"],"format":"int32"},"rollback_volume_name":{"type":["string","null"]},"service_id":{"type":"integer","format":"int32"},"started_at":{"type":["string","null"]},"status":{"type":"string"},"to_image":{"type":"string"},"to_version":{"type":"string"}}},"PipelineStats":{"type":"object","description":"Internal pipeline statistics for self-observability.","required":["metrics_received","metrics_stored","metrics_dropped","spans_received","spans_stored","spans_dropped","logs_received","logs_stored_db","logs_stored_s3","logs_dropped","ingest_errors"],"properties":{"ingest_errors":{"type":"integer","format":"int64","minimum":0},"logs_dropped":{"type":"integer","format":"int64","minimum":0},"logs_received":{"type":"integer","format":"int64","minimum":0},"logs_stored_db":{"type":"integer","format":"int64","minimum":0},"logs_stored_s3":{"type":"integer","format":"int64","minimum":0},"metrics_dropped":{"type":"integer","format":"int64","minimum":0},"metrics_received":{"type":"integer","format":"int64","minimum":0},"metrics_stored":{"type":"integer","format":"int64","minimum":0},"spans_dropped":{"type":"integer","format":"int64","minimum":0},"spans_received":{"type":"integer","format":"int64","minimum":0},"spans_stored":{"type":"integer","format":"int64","minimum":0}}},"PipelineStatsResponse":{"type":"object","required":["stats"],"properties":{"stats":{"$ref":"#/components/schemas/PipelineStats"}}},"PlanComplexity":{"type":"string","description":"Plan complexity indicator","enum":["low","medium","high"]},"PlanMetadata":{"type":"object","description":"Plan metadata","required":["generated_at","generator_version","complexity","warnings"],"properties":{"complexity":{"$ref":"#/components/schemas/PlanComplexity","description":"Estimated complexity (low, medium, high)"},"generated_at":{"type":"string","format":"date-time","description":"When the plan was generated"},"generator_version":{"type":"string","description":"Generator (importer) version"},"warnings":{"type":"array","items":{"type":"string"},"description":"Warnings detected during planning"}}},"PlanSourceBackup":{"type":"object","required":["location","location_was_resolved","format"],"properties":{"created_at":{"type":["string","null"]},"format":{"type":"string","description":"\"walg\", \"pg_dump\", \"unknown\"."},"id":{"type":["integer","null"],"format":"int32","description":"DB id, absent for orphan (S3-scan) backups."},"location":{"type":"string","description":"Resolved S3 location the orchestrator will actually use."},"location_was_resolved":{"type":"boolean","description":"True when the original row's `s3_location` was empty and we resolved\na location by probing S3. The UI shows this as a warning."},"origin_service_name":{"type":["string","null"],"description":"Service that originally produced the backup, if known."},"size_bytes":{"type":["integer","null"],"format":"int64"}}},"PlanTarget":{"type":"object","required":["id","name","container"],"properties":{"container":{"type":"string","description":"Expected Docker container name."},"id":{"type":"integer","format":"int32"},"name":{"type":"string"}}},"PlatformInfo":{"type":"object","description":"Platform compatibility information","required":["os_type","architecture","platforms"],"properties":{"architecture":{"type":"string","description":"System architecture (e.g., \"x86_64\", \"aarch64\")"},"os_type":{"type":"string","description":"Operating system type (e.g., \"linux\", \"windows\", \"darwin\")"},"platforms":{"type":"array","items":{"type":"string"},"description":"List of supported platforms in \"os/arch\" format (e.g., [\"linux/amd64\"])"}}},"PluginManifest":{"type":"object","description":"The complete plugin manifest — the handshake contract.","required":["name","version"],"properties":{"description":{"type":["string","null"],"description":"Short description of what the plugin does"},"display_name":{"type":["string","null"],"description":"Human-readable display name"},"events":{"type":"array","items":{"type":"string"},"description":"Platform event types the plugin subscribes to.\n\nWhen specified, Temps will POST matching events to the plugin's\n`/_events` endpoint. Uses dot-notation event names matching the\nwebhook event types (e.g., \"deployment.succeeded\", \"project.created\").\n\nAvailable events:\n- `deployment.created`, `deployment.succeeded`, `deployment.failed`,\n `deployment.cancelled`, `deployment.ready`\n- `project.created`, `project.deleted`\n- `domain.created`, `domain.provisioned`"},"health_path":{"type":"string","description":"Health check endpoint path (relative to plugin root)"},"name":{"type":"string","description":"Unique plugin identifier (kebab-case, e.g., \"backup-manager\")"},"nav":{"type":"array","items":{"$ref":"#/components/schemas/NavEntry"},"description":"Navigation entries for the UI sidebar"},"requires_db":{"type":"boolean","description":"Whether the plugin needs database access"},"ui":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UiManifest","description":"UI bundle manifest (if the plugin has a UI)"}]},"version":{"type":"string","description":"SemVer version string"}}},"PortMapping":{"type":"object","description":"Port mapping","required":["container_port","protocol","is_primary"],"properties":{"container_port":{"type":"integer","format":"int32","description":"Container port","minimum":0},"host_port":{"type":["integer","null"],"format":"int32","description":"Host port (optional - can be assigned dynamically)","minimum":0},"is_primary":{"type":"boolean","description":"Whether this is the primary HTTP port"},"protocol":{"$ref":"#/components/schemas/Protocol","description":"Protocol (tcp, udp)"}}},"PostgresWalHealth":{"type":"object","required":["probed_at","pg_wal_bytes","max_wal_size_bytes","archive_mode","archive_backlog","stale_slots","oldest_wal_age_secs","warnings"],"properties":{"archive_backlog":{"type":"integer","format":"int64","description":"Number of `archive_status/*.ready` files — un-shipped WAL segments."},"archive_command":{"type":["string","null"],"description":"The literal `archive_command` setting. May be empty or `/bin/true`\nwhen archiving is effectively disabled despite `archive_mode = on`."},"archive_mode":{"$ref":"#/components/schemas/ArchiveMode"},"archiver_failed_count":{"type":["integer","null"],"format":"int64"},"archiver_last_failed_at":{"type":["string","null"],"format":"date-time"},"max_wal_size_bytes":{"type":"integer","format":"int64","description":"`max_wal_size` setting in bytes (parsed from `pg_settings`)."},"oldest_wal_age_secs":{"type":"integer","format":"int64","description":"Age of the oldest WAL file in `pg_wal/` (seconds)."},"pg_wal_bytes":{"type":"integer","format":"int64","description":"Total size of files under `pg_wal/`, from `pg_ls_waldir()`."},"probed_at":{"type":"string","format":"date-time","description":"When the snapshot was taken."},"stale_slots":{"type":"array","items":{"$ref":"#/components/schemas/StaleSlot"}},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/WalWarning"},"description":"Computed warnings, ordered by severity (critical first)."}}},"PresetConfigSchema":{"oneOf":[{"$ref":"#/components/schemas/DockerfilePresetConfig","description":"Configuration for Dockerfile preset"},{"$ref":"#/components/schemas/DockerComposePresetConfig","description":"Configuration for Docker Compose"},{"$ref":"#/components/schemas/NixpacksPresetConfig","description":"Configuration for Nixpacks provider selection and inline build plan"},{"$ref":"#/components/schemas/StaticPresetConfig","description":"Configuration for static site presets (Vite, Next.js, etc.)"}],"description":"Union type for preset configurations\nUse the appropriate configuration type based on your preset"},"PresetInfo":{"type":"object","description":"Detected preset information","required":["path","preset","preset_label","project_type"],"properties":{"compose_files":{"type":["array","null"],"items":{"type":"string"},"description":"Compose file paths found in the repository (only for docker-compose preset)"},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Default exposed port for this preset"},"icon_url":{"type":["string","null"],"description":"Icon URL for this preset"},"path":{"type":"string","description":"Path where preset was detected (empty for root)"},"preset":{"type":"string","description":"Preset slug (e.g., \"nextjs\", \"fastapi\")"},"preset_label":{"type":"string","description":"Human-readable preset label"},"project_type":{"type":"string","description":"Project type (e.g., \"frontend\", \"backend\", \"fullstack\")"}}},"PresetResponse":{"type":"object","required":["slug","label","icon_url","project_type","description"],"properties":{"default_port":{"type":["integer","null"],"format":"int32","description":"Default port the application listens on (None for static sites)","example":3000,"minimum":0},"description":{"type":"string","description":"Description of what this preset does"},"icon_url":{"type":"string","description":"Icon URL for the preset"},"label":{"type":"string","description":"Display name/label for the preset"},"project_type":{"type":"string","description":"Project type (server or static)"},"slug":{"type":"string","description":"Unique identifier slug for the preset"}}},"PreviewGatewaySettings":{"type":"object","description":"Workspace preview gateway settings.\n\nThe preview gateway is a single shared Docker container that lives on the\n`temps-sandbox-net` network and routes requests to workspace sandbox dev\nservers based on the `Host` header (`ws--.`).\n`temps serve` reconciles this container on startup; these settings let an\noperator override the image, host port, and auto-upgrade behavior.","properties":{"auto_upgrade":{"type":"boolean","description":"When true (default), the supervisor will pull and apply the image\npinned in the Temps binary on every startup. When false, the\ncurrently-running image is left alone — operators upgrade manually\nfrom the settings UI.","default":true,"example":true},"host_port":{"type":"integer","format":"int32","description":"Host port to publish the gateway on (always bound to 127.0.0.1).\nPingora forwards `ws-*` traffic to this port after authenticating.","default":8090,"example":8090,"minimum":0},"image":{"type":"string","description":"Docker image reference for the gateway. Pinned per Temps release.\nOperators can override this to test a custom build.","default":"ghcr.io/gotempsh/temps-preview-gateway:latest","example":"ghcr.io/gotempsh/temps-preview-gateway:latest"},"shared_secret":{"type":"string","description":"Shared secret the host-side Pingora sends on every forwarded preview\nrequest via `X-Temps-Preview-Token`; the gateway rejects requests\nwithout it. Auto-generated on first boot, persisted in DB so the\nsecret is stable across `temps serve` restarts regardless of cwd,\n`TEMPS_DATA_DIR`, or data-dir changes. MUST be masked (`***`) in any\nAPI response — never expose it over HTTP.","default":"","example":""}}},"PreviewGatewaySettingsMasked":{"type":"object","description":"Preview gateway settings with `shared_secret` elided.","required":["image","host_port","auto_upgrade","shared_secret_set"],"properties":{"auto_upgrade":{"type":"boolean"},"host_port":{"type":"integer","format":"int32","minimum":0},"image":{"type":"string"},"shared_secret_set":{"type":"boolean"}}},"PreviewGatewaySettingsResponse":{"type":"object","required":["image","host_port","auto_upgrade","default_image","default_host_port"],"properties":{"auto_upgrade":{"type":"boolean"},"default_host_port":{"type":"integer","format":"int32","description":"The compile-time default host port.","minimum":0},"default_image":{"type":"string","description":"The compile-time default image — exposed so the UI can offer a\n\"Reset to default\" link without round-tripping."},"host_port":{"type":"integer","format":"int32","minimum":0},"image":{"type":"string"}}},"PricingResponse":{"type":"object","required":["models"],"properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/ModelPricing"}}}},"ProblemDetails":{"type":"object","description":"Representation of a Problem error to return to the client.\nFollows RFC 7807 - Problem Details for HTTP APIs","required":["title","extensions"],"properties":{"detail":{"type":["string","null"],"description":"A human-readable explanation specific to this occurrence of the problem","example":"The server encountered an unexpected condition"},"extensions":{"type":"object","description":"Additional properties of the problem","additionalProperties":true},"instance":{"type":["string","null"],"description":"A URI reference that identifies the specific occurrence of the problem","example":"/account/12345/msgs/abc"},"title":{"type":"string","description":"A short, human-readable summary of the problem type","example":"Internal Server Error"},"type":{"type":["string","null"],"description":"A URI reference that identifies the problem type","example":"https://example.com/probs/out-of-memory"}},"example":{"type":"https://example.com/probs/out-of-memory","title":"Internal Server Error","detail":"The server encountered an unexpected condition","instance":"/account/12345/msgs/abc","additional_info":"Custom field with additional details"}},"ProjectConfiguration":{"type":"object","description":"Project-level configuration","required":["name","slug","project_type","is_web_app"],"properties":{"is_web_app":{"type":"boolean","description":"Whether this is a web application"},"name":{"type":"string","description":"Proposed project name"},"project_type":{"$ref":"#/components/schemas/ProjectType","description":"Project type"},"slug":{"type":"string","description":"Proposed slug (URL-safe identifier)"}}},"ProjectDSNResponse":{"type":"object","required":["id","project_id","name","public_key","dsn","created_at","is_active","event_count"],"properties":{"created_at":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"dsn":{"type":"string"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_count":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"public_key":{"type":"string"}}},"ProjectDashboardAnalytics":{"type":"object","description":"Analytics data for a single project in the dashboard batch response","required":["project_id","unique_visitors","previous_unique_visitors","hourly_visits"],"properties":{"hourly_visits":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"},"description":"Hourly sparkline data points"},"previous_unique_visitors":{"type":"integer","format":"int64","description":"Unique visitor count in the previous period (same duration, shifted back)"},"project_id":{"type":"integer","format":"int32"},"trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change from previous period (positive = growth, negative = decline)\nNull when previous period had zero visitors (no baseline to compare)"},"unique_visitors":{"type":"integer","format":"int64","description":"Unique visitor count in the current time range"}}},"ProjectHealthSummary":{"type":"object","description":"Health summary for a single project (last 1 hour)","required":["project_id","total_requests","total_errors","avg_response_time_ms","error_rate","status"],"properties":{"avg_response_time_ms":{"type":"number","format":"double","description":"Average response time in ms"},"error_rate":{"type":"number","format":"double","description":"Error rate as a percentage (0-100)"},"project_id":{"type":"integer","format":"int32"},"status":{"type":"string","description":"Health status: \"healthy\", \"degraded\", \"down\", \"unknown\""},"total_errors":{"type":"integer","format":"int64","description":"Total server errors (status >= 500) in the period"},"total_requests":{"type":"integer","format":"int64","description":"Total requests in the period"}}},"ProjectInfo":{"type":"object","required":["id","slug","created_at"],"properties":{"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"id":{"type":"integer","format":"int32"},"slug":{"type":"string"}}},"ProjectMonitorHealth":{"type":"object","description":"Health summary for a single project based on its production monitors","required":["project_id","status"],"properties":{"project_id":{"type":"integer","format":"int32"},"status":{"type":"string","description":"Overall status: \"operational\", \"degraded\", \"down\", or \"no_monitors\""}}},"ProjectPresetResponse":{"type":"object","required":["path","preset","presetLabel","projectType"],"properties":{"composeFiles":{"type":["array","null"],"items":{"type":"string"},"description":"Compose file paths found in the repository (only for docker-compose preset)"},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Default exposed port for this preset (e.g., 3000 for Next.js, 8000 for FastAPI)"},"iconUrl":{"type":["string","null"],"description":"Icon URL for the preset"},"path":{"type":"string"},"preset":{"type":"string"},"presetLabel":{"type":"string"},"projectType":{"type":"string","description":"Project type category (e.g., \"frontend\", \"backend\", \"fullstack\")"}}},"ProjectQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"ProjectRef":{"type":"object","description":"A lightweight project descriptor included in `UnifiedTrace`.","required":["project_id","project_name","project_slug"],"properties":{"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link a span back into its owning project's trace view."}}},"ProjectResponse":{"type":"object","required":["id","slug","name","directory","main_branch","created_at","updated_at","deployment_config","attack_mode","ai_write_actions_enabled","error_source_context_enabled","enable_preview_environments","preview_envs_on_demand","preview_envs_idle_timeout_seconds","preview_envs_wake_timeout_seconds","source_type","cross_project_trace_sharing"],"properties":{"ai_alert_summaries_enabled":{"type":["boolean","null"],"description":"Opt-in to AI summarization of metric alert notifications (NULL/false = off)."},"ai_debug_chat_enabled":{"type":["boolean","null"],"description":"Opt-in to AI debugging chat, e.g. on deployment failures (NULL/false = off)."},"ai_write_actions_enabled":{"type":"boolean","description":"Opt-in to AI propose-then-confirm write capability (false = off)."},"attack_mode":{"type":"boolean","description":"Attack mode - when enabled, requires CAPTCHA verification for all project environments"},"created_at":{"type":"integer","format":"int64"},"cross_project_trace_sharing":{"type":"boolean","description":"ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed\nfrom cross-project discovery results. Default true (consistent with the\nOSS global-observability model where any OtelRead holder can query any\nproject's telemetry)."},"deployment_config":{"$ref":"#/components/schemas/DeploymentConfig","description":"Deployment configuration (resources, autoscaling, features)"},"directory":{"type":"string"},"enable_preview_environments":{"type":"boolean","description":"Enable automatic preview environment creation for each branch"},"error_source_context_enabled":{"type":"boolean","description":"Opt-in to native error-tracking source context (false = off). When on,\nTemps stores uploaded source files and shows source code in stack traces."},"error_source_root":{"type":["string","null"],"description":"Where auto-capture reads source from (relative to the checkout). Null =\nthe deployment's Docker build context."},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"],"description":"Git clone URL for the repository (used for public repos without a provider connection)"},"gitlab_webhook_id":{"type":["integer","null"],"format":"int32","description":"GitLab webhook ID installed on the connected repository.\n`null` when no GitLab webhook is installed (not connected to GitLab,\nor webhook was removed / never created).","example":42},"id":{"type":"integer","format":"int32"},"last_deployment":{"type":["integer","null"],"format":"int64"},"main_branch":{"type":"string"},"name":{"type":"string"},"preset":{"type":["string","null"]},"preset_config":{"description":"Preset-specific configuration (Dockerfile path, build context, etc.)"},"preview_envs_idle_timeout_seconds":{"type":"integer","format":"int32","description":"Idle timeout (seconds) for on-demand preview environments."},"preview_envs_on_demand":{"type":"boolean","description":"When true, newly-created preview environments default to on-demand mode\n(containers stop after the configured idle timeout to save resources)."},"preview_envs_wake_timeout_seconds":{"type":"integer","format":"int32","description":"Wake timeout (seconds) for on-demand preview environments."},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"slug":{"type":"string"},"source_type":{"$ref":"#/components/schemas/SourceType","description":"Source type for deployments (git, docker_image, or static_files)"},"updated_at":{"type":"integer","format":"int64"}}},"ProjectSecretEnvironmentInfo":{"type":"object","required":["id","name","main_url"],"properties":{"id":{"type":"integer","format":"int32"},"main_url":{"type":"string"},"name":{"type":"string"}}},"ProjectSecretResponse":{"type":"object","description":"Project secret metadata. There is deliberately no `value` field — secret\nplaintext is never returned after creation. Callers that need the value\nmust read it from the mounted file inside the container.","required":["id","project_id","key","include_in_preview","created_at","updated_at","environments"],"properties":{"created_at":{"type":"integer","format":"int64"},"environments":{"type":"array","items":{"$ref":"#/components/schemas/ProjectSecretEnvironmentInfo"}},"id":{"type":"integer","format":"int32"},"include_in_preview":{"type":"boolean"},"key":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"integer","format":"int64"}}},"ProjectServiceInfo":{"type":"object","required":["id","project","service"],"properties":{"id":{"type":"integer","format":"int32"},"project":{"$ref":"#/components/schemas/ProjectInfo"},"service":{"$ref":"#/components/schemas/ExternalServiceInfo"}}},"ProjectStatisticsResponse":{"type":"object","required":["total_count"],"properties":{"total_count":{"type":"integer","format":"int64"}}},"ProjectStatsBreakdown":{"type":"object","required":["project_id","unique_visitors","total_visits","total_page_views","bounce_rate","engagement_rate"],"properties":{"bounce_rate":{"type":"number","format":"double"},"engagement_rate":{"type":"number","format":"double"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":["string","null"]},"total_page_views":{"type":"integer","format":"int64"},"total_visits":{"type":"integer","format":"int64"},"unique_visitors":{"type":"integer","format":"int64"}}},"ProjectType":{"type":"string","description":"Project type enumeration","enum":["static","docker","buildpack","git"]},"ProjectUsageInfoResponse":{"type":"object","required":["id","name","slug","connection_id","connection_name"],"properties":{"connection_id":{"type":"integer","format":"int32"},"connection_name":{"type":"string"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"ProjectsHealthResponse":{"type":"object","description":"Batch health summary response","required":["projects"],"properties":{"projects":{"type":"object","description":"Health summaries keyed by project ID","additionalProperties":{"$ref":"#/components/schemas/ProjectHealthSummary"},"propertyNames":{"type":"string"}}}},"ProjectsMonitorHealthResponse":{"type":"object","description":"Batch response for projects health","required":["projects"],"properties":{"projects":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ProjectMonitorHealth"},"propertyNames":{"type":"string"}}}},"PromoteDeploymentRequest":{"type":"object","required":["target_environment_id"],"properties":{"target_environment_id":{"type":"integer","format":"int32","description":"Target environment ID to promote the deployment to"}}},"PropertyBreakdownItem":{"type":"object","required":["value","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"value":{"type":"string"}}},"PropertyBreakdownQuery":{"type":"object","description":"Query parameters for property breakdown (group by column)","required":["start_date","end_date","group_by"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"event_name":{"type":["string","null"],"description":"Optional event name filter (e.g., \"page_view\", \"click\")"},"filter_browser":{"type":["string","null"],"description":"Filter by browser name (for browser version drill-downs)"},"filter_channel":{"type":["string","null"],"description":"Filter by channel name (for channel -> referrer drill-downs)"},"filter_country":{"type":["string","null"],"description":"Filter by country (for region/city drill-downs). Requires geolocation join."},"filter_os":{"type":["string","null"],"description":"Filter by operating system name (for OS version drill-downs)"},"filter_referrer":{"type":["string","null"],"description":"Filter by referrer hostname (for referrer -> pages drill-downs)"},"filter_region":{"type":["string","null"],"description":"Filter by region (for city drill-downs). Requires geolocation join."},"group_by":{"$ref":"#/components/schemas/PropertyColumn","description":"Property column to group by"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of results to return (default: 20, max: 100)"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"PropertyBreakdownResponse":{"type":"object","required":["property","items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PropertyBreakdownItem"}},"property":{"type":"string"},"total":{"type":"integer","format":"int64"}}},"PropertyColumn":{"type":"string","enum":["channel","device_type","browser","browser_version","operating_system","operating_system_version","utm_source","utm_medium","utm_campaign","utm_term","utm_content","referrer_hostname","language","event_type","event_name","page_path","pathname","country","region","city"]},"PropertyTimelineItem":{"type":"object","required":["timestamp","value","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"},"value":{"type":"string"}}},"PropertyTimelineQuery":{"type":"object","description":"Query parameters for property timeline (group by column over time)","required":["start_date","end_date","group_by"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level"},"bucket_size":{"type":["string","null"],"description":"Time bucket size: \"hour\", \"day\", \"week\", \"month\" (default: auto-detect)"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"event_name":{"type":["string","null"],"description":"Optional event name filter"},"group_by":{"$ref":"#/components/schemas/PropertyColumn","description":"Property column to group by"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"PropertyTimelineResponse":{"type":"object","required":["property","bucket_size","items"],"properties":{"bucket_size":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PropertyTimelineItem"}},"property":{"type":"string"}}},"Protocol":{"type":"string","description":"Network protocol","enum":["tcp","udp"]},"ProviderCatalogDto":{"type":"object","description":"One catalog entry rendered for the settings UI.","required":["id","name","install_command","auth_command","auth_flavors","models","credential_saved","supports_max_turns"],"properties":{"auth_command":{"type":"string"},"auth_flavors":{"type":"array","items":{"$ref":"#/components/schemas/AuthFlavorDto"}},"credential_saved":{"type":"boolean","description":"True when a credential is currently saved for this provider in the\nsettings JSON. Lets the UI render \"Configured\" badges without the\nfrontend having to inspect the encrypted blob."},"current_auth_type":{"type":["string","null"],"description":"Currently saved auth flavor id (when `credential_saved` is true).\n`None` when no credential is saved yet."},"default_model":{"type":["string","null"],"description":"Currently saved default model id for this provider, if one was\npicked. `None` means \"use the CLI's own default\" — the UI renders\nthat as \"Use provider default\"."},"id":{"type":"string"},"install_command":{"type":"string"},"max_turns_analysis":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer analysis phase. `None` = built-in\ndefault (10). Only enforced for CLIs with a turn flag (Claude Code)."},"max_turns_feedback":{"type":["integer","null"],"format":"int32","description":"Default max turns for autofixer feedback rounds. `None` = built-in\ndefault (10)."},"max_turns_fix":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer fix phase. `None` = built-in\ndefault (20)."},"models":{"type":"array","items":{"type":"string"},"description":"Model ids this provider accepts, in display order. The first entry is\nthe recommended default. Empty when the provider doesn't expose model\nselection (e.g. OpenCode), which the UI uses to hide the dropdown."},"name":{"type":"string"},"supports_max_turns":{"type":"boolean","description":"True when this provider's CLI supports enforcing a turn cap. False\nfor Codex/OpenCode, which run to completion — the UI labels their\nmax-turns inputs accordingly."}}},"ProviderCatalogResponse":{"type":"object","required":["default_provider","providers"],"properties":{"default_provider":{"type":"string","description":"Active provider id from `agent_sandbox.default_provider`. The settings\nUI uses this to highlight which card is the active one."},"providers":{"type":"array","items":{"$ref":"#/components/schemas/ProviderCatalogDto"}}}},"ProviderConfig":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/StripeConfig"},{"type":"object","required":["provider"],"properties":{"provider":{"type":"string","enum":["stripe"]}}}]},{"allOf":[{"$ref":"#/components/schemas/LemonSqueezyConfig"},{"type":"object","required":["provider"],"properties":{"provider":{"type":"string","enum":["lemon_squeezy"]}}}]}],"description":"Provider-specific integration settings persisted in\n`revenue_integrations.config`.\n\nThe tag is the lowercase provider name, so adding a new provider\nmeans adding a new variant and the existing rows are untouched.\nOld rows (pre-config) and rows with `NULL` config are treated as\n\"accept all events, no filtering\" via [`ProviderConfig::default_for`]."},"ProviderConfigMasked":{"type":"object","required":["auth_type","credential_saved","extra"],"properties":{"auth_type":{"type":"string"},"credential_saved":{"type":"boolean","description":"True if a credential is stored for this provider. The encrypted blob\nis never returned over HTTP."},"default_model":{"type":["string","null"]},"extra":{}}},"ProviderDeletionCheckResponse":{"type":"object","required":["can_delete","projects_in_use","message"],"properties":{"can_delete":{"type":"boolean"},"message":{"type":"string"},"projects_in_use":{"type":"array","items":{"$ref":"#/components/schemas/ProjectUsageInfoResponse"}}}},"ProviderDescriptor":{"type":"object","required":["name","display_name","recommended_events"],"properties":{"display_name":{"type":"string"},"name":{"type":"string"},"recommended_events":{"type":"array","items":{"type":"string"}}}},"ProviderKeyResponse":{"type":"object","required":["id","provider","display_name","api_key_masked","is_active","created_at","updated_at"],"properties":{"api_key_masked":{"type":"string","description":"Masked API key (only last 4 chars visible)"},"base_url":{"type":["string","null"]},"created_at":{"type":"string"},"default_model":{"type":["string","null"],"description":"Model id this provider serves (NULL → per-provider default)."},"display_name":{"type":"string"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"provider":{"type":"string"},"updated_at":{"type":"string"}}},"ProviderMetadata":{"type":"object","required":["service_type","display_name","description","icon_url","color"],"properties":{"color":{"type":"string","example":"#336791"},"description":{"type":"string","example":"Relational database management system"},"display_name":{"type":"string","example":"PostgreSQL"},"icon_url":{"type":"string","example":"https://cdn.simpleicons.org/postgresql"},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"}}},"ProviderResponse":{"type":"object","required":["id","name","provider_type","auth_method","is_active","is_default","created_at","updated_at"],"properties":{"auth_method":{"type":"string"},"base_url":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"is_default":{"type":"boolean"},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"ProviderUsage":{"type":"object","required":["provider","request_count","input_tokens","output_tokens","avg_latency_ms","error_count"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"input_tokens":{"type":"integer","format":"int64"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_count":{"type":"integer","format":"int64"}}},"ProvisionResponse":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/DomainError"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["complete"]}}}]},{"allOf":[{"$ref":"#/components/schemas/DomainChallengeResponse"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["pending"]}}}]}]},"ProxyLogResponse":{"type":"object","description":"Response model for proxy logs","required":["id","timestamp","method","path","host","status_code","request_source","is_system_request","routing_status","request_id"],"properties":{"bot_name":{"type":["string","null"]},"browser":{"type":["string","null"]},"browser_version":{"type":["string","null"]},"cache_status":{"type":["string","null"]},"client_ip":{"type":["string","null"]},"container_id":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"host":{"type":"string"},"id":{"type":"integer","format":"int32"},"ip_geolocation_id":{"type":["integer","null"],"format":"int32"},"is_bot":{"type":["boolean","null"]},"is_system_request":{"type":"boolean"},"method":{"type":"string"},"operating_system":{"type":["string","null"]},"path":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"query_string":{"type":["string","null"]},"referrer":{"type":["string","null"]},"request_id":{"type":"string"},"request_size_bytes":{"type":["integer","null"],"format":"int64"},"request_source":{"type":"string"},"response_size_bytes":{"type":["integer","null"],"format":"int64"},"response_time_ms":{"type":["integer","null"],"format":"int32"},"routing_status":{"type":"string"},"session_id":{"type":["integer","null"],"format":"int32"},"status_code":{"type":"integer","format":"int32"},"timestamp":{"type":"string"},"upstream_host":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"ProxyLogsPaginatedResponse":{"type":"object","description":"Paginated response for proxy logs","required":["logs","total","page","page_size","total_pages"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/ProxyLogResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0},"total_pages":{"type":"integer","format":"int64","minimum":0}}},"ProxyRequest":{"type":"object","description":"Proxy configuration for email validation","required":["host","port"],"properties":{"host":{"type":"string","description":"Proxy host","example":"proxy.example.com"},"password":{"type":["string","null"],"description":"Optional proxy password"},"port":{"type":"integer","format":"int32","description":"Proxy port","example":1080,"minimum":0},"username":{"type":["string","null"],"description":"Optional proxy username"}}},"PublicHostnameStrategy":{"type":"string","description":"Public hostname generation mode for Temps-managed preview routes.\n\nThe mode is stored per managed domain (`dns_managed_domains.generated_hostname_mode`)\nrather than globally, so a provider such as Cloudflare can offer the flat layout\nrequired by its Universal SSL wildcard cert without changing every domain's behaviour.","enum":["standard","flat"]},"PublicPresetResponse":{"type":"object","description":"Response for preset detection","required":["branch","presets"],"properties":{"branch":{"type":"string","description":"Branch name where presets were detected"},"presets":{"type":"array","items":{"$ref":"#/components/schemas/PresetInfo"},"description":"List of detected presets"}}},"PublicRepositoryInfo":{"type":"object","description":"Public repository information","required":["owner","name","full_name","default_branch","stars","forks"],"properties":{"default_branch":{"type":"string","description":"Default branch name"},"description":{"type":["string","null"],"description":"Repository description"},"forks":{"type":"integer","format":"int32","description":"Fork count"},"full_name":{"type":"string","description":"Full repository name (owner/repo)"},"language":{"type":["string","null"],"description":"Primary programming language"},"name":{"type":"string","description":"Repository name"},"owner":{"type":"string","description":"Repository owner"},"stars":{"type":"integer","format":"int32","description":"Star count"}}},"PurgeLogsRequest":{"type":"object","required":["before"],"properties":{"before":{"type":"string","description":"Delete all logs before this timestamp (ISO 8601)"}}},"PushImageRequest":{"type":"object","description":"Request to push an external image","required":["image_ref"],"properties":{"image_ref":{"type":"string"},"metadata":{}}},"PushedExternalImageResponse":{"type":"object","description":"Response for in-memory external image operations (legacy push flow).\n\nRenamed to avoid shadowing the richer database-backed `ExternalImageResponse`\nin `handlers/remote_deployments.rs`. The two types serve different routes\n(`/images` ephemeral push vs `/external-images` registered images).","required":["id","image_ref","pushed_at"],"properties":{"digest":{"type":["string","null"]},"id":{"type":"string"},"image_ref":{"type":"string"},"pushed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"size":{"type":["integer","null"],"format":"int64","minimum":0}}},"QueryDataRequest":{"type":"object","properties":{"filters":{"description":"JSON filters (backend-specific format)"},"limit":{"type":"integer","description":"Maximum number of rows to return","example":100,"minimum":0},"offset":{"type":"integer","description":"Number of rows to skip","example":0,"minimum":0},"sort_by":{"type":["string","null"],"description":"Sort by field name"},"sort_order":{"type":["string","null"],"description":"Sort order (asc/desc)"}}},"QueryDataResponse":{"type":"object","required":["fields","rows","total_count","returned_count","execution_time_ms"],"properties":{"execution_time_ms":{"type":"integer","format":"int64","description":"Query execution time in milliseconds","example":45,"minimum":0},"fields":{"type":"array","items":{"$ref":"#/components/schemas/FieldResponse"},"description":"Field definitions"},"returned_count":{"type":"integer","description":"Number of rows returned in this response","example":100,"minimum":0},"rows":{"type":"array","items":{},"description":"Data rows (array of JSON objects)"},"total_count":{"type":"integer","format":"int64","description":"Total number of rows matching the query (before limit/offset)","example":1234,"minimum":0}}},"QuotaResponse":{"type":"object","required":["quota"],"properties":{"quota":{"$ref":"#/components/schemas/StorageQuota"}}},"RateLimitConfig":{"type":"object","description":"Rate limiting configuration (subset of global RateLimitSettings)","properties":{"blacklistIps":{"type":"array","items":{"type":"string"},"description":"Blacklist specific IPs for this project/environment"},"maxRequestsPerHour":{"type":["integer","null"],"format":"int32","description":"Override rate limit per hour","minimum":0},"maxRequestsPerMinute":{"type":["integer","null"],"format":"int32","description":"Override rate limit per minute","minimum":0},"whitelistIps":{"type":"array","items":{"type":"string"},"description":"Whitelist specific IPs for this project/environment"}}},"RateLimitSettings":{"type":"object","properties":{"blacklist_ips":{"type":"array","items":{"type":"string"},"default":[]},"enabled":{"type":"boolean","default":false},"max_requests_per_hour":{"type":"integer","format":"int32","default":1000,"minimum":0},"max_requests_per_minute":{"type":"integer","format":"int32","default":60,"minimum":0},"whitelist_ips":{"type":"array","items":{"type":"string"},"default":[]}}},"ReachabilityStatus":{"type":"string","description":"Email reachability status","enum":["safe","risky","invalid","unknown"]},"ReadFileResponse":{"type":"object","required":["path","contents_b64","size"],"properties":{"contents_b64":{"type":"string","description":"File contents, base64-encoded. Symmetric with `WriteFileBody`."},"path":{"type":"string"},"size":{"type":"integer","format":"int64","minimum":0}}},"RecentActivityQuery":{"type":"object","description":"Query parameters for recent activity endpoint","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32","description":"Environment ID (optional)"},"limit":{"type":["integer","null"],"format":"int32","description":"Max number of events to return (default: 50, max: 100)"},"project_id":{"type":"integer","format":"int32","description":"Project ID"},"since_id":{"type":["integer","null"],"format":"int64","description":"Return events with ID greater than this (for cursor-based polling)"}}},"RecentActivityResponse":{"type":"object","description":"Response for recent activity events endpoint","required":["events","count"],"properties":{"count":{"type":"integer","description":"Total events returned","minimum":0},"events":{"type":"array","items":{"$ref":"#/components/schemas/ActivityEvent"},"description":"Recent events, newest first"}}},"RecentEventResponse":{"type":"object","required":["occurred_at","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"event_type":{"type":"string"},"mrr_minor":{"type":["integer","null"],"format":"int64"},"occurred_at":{"type":"string","format":"date-time"}}},"RecentQueryParams":{"type":"object","properties":{"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"cost_gt":{"type":["integer","null"],"format":"int64","description":"Cost strictly greater-than, in microcents"},"cost_gte":{"type":["integer","null"],"format":"int64","description":"Cost greater-than-or-equal, in microcents"},"cost_lt":{"type":["integer","null"],"format":"int64","description":"Cost strictly less-than, in microcents"},"cost_lte":{"type":["integer","null"],"format":"int64","description":"Cost less-than-or-equal, in microcents"},"limit":{"type":["integer","null"],"format":"int64","description":"Page size (defaults to 20, max 50)","minimum":0},"model":{"type":["string","null"],"description":"Filter by model name"},"offset":{"type":["integer","null"],"format":"int64","description":"Number of results to skip for pagination (defaults to 0)","minimum":0},"provider":{"type":["string","null"],"description":"Filter by provider name"},"status":{"type":["integer","null"],"format":"int32","description":"Filter by HTTP status code (exact match)"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"tokens_gt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly greater-than"},"tokens_gte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) greater-than-or-equal"},"tokens_lt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly less-than"},"tokens_lte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) less-than-or-equal"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"RecordListResponse":{"type":"object","description":"Record list response","required":["records"],"properties":{"records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecord"}}}},"RecoveryTarget":{"oneOf":[{"type":"object","description":"Recover to a specific timestamp.","required":["time","kind"],"properties":{"kind":{"type":"string","enum":["time"]},"time":{"type":"string","format":"date-time"}}},{"type":"object","description":"Recover to a specific transaction id (Postgres).","required":["xid","kind"],"properties":{"kind":{"type":"string","enum":["xid"]},"xid":{"type":"string"}}},{"type":"object","description":"Recover to a specific log sequence number (Postgres).","required":["lsn","kind"],"properties":{"kind":{"type":"string","enum":["lsn"]},"lsn":{"type":"string"}}},{"type":"object","description":"Recover to a named restore point created via `pg_create_restore_point` (Postgres).","required":["name","kind"],"properties":{"kind":{"type":"string","enum":["name"]},"name":{"type":"string"}}}],"description":"Engine-specific recovery target for PITR.\n\nPostgres honors all variants; Redis/Mongo/S3 will likely reject non-Time\nvariants or define their own semantics when they grow PITR support."},"ReferrerCount":{"type":"object","required":["referrer","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"referrer":{"type":"string"}}},"ReferrersAnalyticsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"RegenerateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]}}},"RegisterImageRequest":{"type":"object","required":["image_ref"],"properties":{"digest":{"type":["string","null"],"description":"Image digest (sha256:...)","example":"sha256:abc123def456"},"image_ref":{"type":"string","description":"Docker image reference (e.g., \"ghcr.io/org/app:v1.0\")","example":"ghcr.io/myorg/myapp:v1.0"},"metadata":{"description":"Additional metadata"},"tag":{"type":["string","null"],"description":"Image tag","example":"v1.0"}}},"RegisterNodeApiRequest":{"type":"object","required":["name","token","address","private_address"],"properties":{"address":{"type":"string","description":"Node's reachable address (e.g., \"10.100.0.2\" or \"192.168.1.50\")"},"csr_pem":{"type":["string","null"],"description":"Node-generated certificate signing request (PEM) for multi-node mTLS\n(ADR-020 WS-2.1). When present, the control plane signs it with the\ncluster CA and returns the leaf + CA cert. Optional — token-only nodes\n(legacy / edge) still register without one."},"edge_public_key":{"type":["string","null"],"description":"X25519 public key for ECIES certificate encryption (base64-encoded, edge nodes only)"},"join_token":{"type":["string","null"],"description":"Join token to authorize this registration (must match the token generated in Settings)"},"labels":{"description":"Labels for scheduling (e.g., {\"region\": \"us-east\", \"gpu\": \"true\"})"},"name":{"type":"string","description":"Unique name for this node"},"prior_token":{"type":["string","null"],"description":"The node's *current* token, supplied to prove possession when\nre-registering (changing the identity of) a node that already exists.\nOptional; only needed to rebind a still-live node. (ADR-020 WS-1.2.)"},"private_address":{"type":"string","description":"Private/WireGuard address for inter-node communication"},"public_endpoint":{"type":["string","null"],"description":"Public endpoint for WireGuard (e.g., \"203.0.113.1:51820\")"},"role":{"type":["string","null"],"description":"Node role (default: \"worker\")"},"token":{"type":"string","description":"Registration token (plaintext, will be hashed before storage)"},"wg_public_key":{"type":["string","null"],"description":"WireGuard public key"}}},"RegisterNodeResponse":{"type":"object","required":["id","name","status","message"],"properties":{"ca_cert_pem":{"type":["string","null"],"description":"The cluster CA certificate (PEM) the node pins as its trust root.\nPresent only when a `csr_pem` was supplied. (ADR-020 WS-2.1.)"},"cert_pem":{"type":["string","null"],"description":"The signed per-node leaf certificate (PEM) the agent serves as its TLS\nserver cert. Present only when a `csr_pem` was supplied. (ADR-020 WS-2.1.)"},"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"RegisterRequest":{"type":"object","required":["email","password","name"],"properties":{"email":{"type":"string"},"name":{"type":"string"},"password":{"type":"string"}}},"ReinstallWebhookResponse":{"type":"object","description":"Response for `POST /projects/{project_id}/gitlab/reinstall-webhook`","required":["hook_id","message"],"properties":{"hook_id":{"type":"integer","format":"int32","description":"The new GitLab hook ID that was installed."},"message":{"type":"string","description":"Human-readable status message."}}},"ReleaseListResponse":{"type":"object","required":["releases"],"properties":{"releases":{"type":"array","items":{"type":"string"}}}},"ReloadResponse":{"type":"object","description":"Response from the reload endpoint.","required":["loaded","plugins","message"],"properties":{"loaded":{"type":"integer","description":"Number of plugins successfully loaded after reload","minimum":0},"message":{"type":"string","description":"Human-readable status message"},"plugins":{"type":"array","items":{"type":"string"},"description":"Names of loaded plugins"}}},"RemoteDeploymentResponse":{"type":"object","required":["id","project_id","environment_id","slug","state","source_type","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"slug":{"type":"string"},"source_type":{"type":"string"},"state":{"type":"string"}}},"RemoveNodeResponse":{"type":"object","required":["id","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"}}},"RenameConversationRequest":{"type":"object","required":["title"],"properties":{"title":{"type":"string","description":"New human-facing title. Trimmed; must be non-empty after trimming."}}},"RepositoryListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"language":{"type":["string","null"]},"owner":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"private":{"type":["boolean","null"]},"search":{"type":["string","null"]},"sort":{"type":["string","null"]}}},"RepositoryListResponse":{"type":"object","required":["repositories","total_count"],"properties":{"repositories":{"type":"array","items":{"$ref":"#/components/schemas/RepositoryResponse"}},"total_count":{"type":"integer","minimum":0}}},"RepositoryPresetResponse":{"type":"object","required":["repository_id","owner","name","presets","calculated_at"],"properties":{"calculated_at":{"type":"string","format":"date-time"},"name":{"type":"string"},"owner":{"type":"string"},"presets":{"type":"array","items":{"$ref":"#/components/schemas/ProjectPresetResponse"}},"repository_id":{"type":"integer","format":"int32"}}},"RepositoryResponse":{"type":"object","required":["id","owner","name","full_name","private","default_branch","created_at","updated_at","pushed_at","git_provider_connection_id"],"properties":{"clone_url":{"type":["string","null"],"description":"HTTPS clone URL (e.g., https://github.com/owner/repo.git)"},"created_at":{"type":"string","format":"date-time"},"default_branch":{"type":"string"},"description":{"type":["string","null"]},"full_name":{"type":"string"},"git_provider_connection_id":{"type":"integer","format":"int32","description":"ID of the git provider connection this repository was synced from."},"id":{"type":"integer","format":"int32"},"language":{"type":["string","null"]},"name":{"type":"string"},"owner":{"type":"string"},"preset":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ProjectPresetResponse"}},"private":{"type":"boolean"},"pushed_at":{"type":"string","format":"date-time"},"ssh_url":{"type":["string","null"],"description":"SSH clone URL (e.g., git@github.com:owner/repo.git)"},"updated_at":{"type":"string","format":"date-time"}}},"RepositorySyncStartedResponse":{"type":"object","description":"Returned by `POST /git-connections/{id}/sync` to acknowledge that a\nsync has been kicked off in the background. Clients should poll the\nconnection's `syncing` and `synced_repository_count` fields to track\nprogress rather than waiting on this response.","required":["connection_id","syncing","started_at"],"properties":{"connection_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time"},"syncing":{"type":"boolean"}}},"RequestRow":{"type":"object","required":["id","ts","method","host","path","status","request_headers","response_headers","headers_truncated"],"properties":{"client_ip":{"type":["string","null"]},"country":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_group_id":{"type":["integer","null"],"format":"int32"},"headers_truncated":{"type":"boolean"},"host":{"type":"string"},"id":{"type":"string","description":"The request's unique `request_id` (assigned by the proxy). Used as the\nrow identity instead of the storage PK because the ClickHouse backend\nhas no serial id (rows come back with `id = 0`) while `request_id` is\nunique and present on both backends."},"latency_ms":{"type":["integer","null"],"format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"query_string":{"type":["string","null"]},"referrer":{"type":["string","null"]},"request_headers":{},"response_headers":{},"status":{"type":"integer","format":"int32"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"},"user_agent":{"type":["string","null"]}}},"ResetPasswordRequest":{"type":"object","required":["token","new_password"],"properties":{"new_password":{"type":"string"},"token":{"type":"string"}}},"ResizeSandboxBody":{"type":"object","required":["disk_size_mb"],"properties":{"disk_size_mb":{"type":"integer","format":"int64","description":"New root disk size in MB. Grow-only; must exceed the current size.","minimum":0}},"additionalProperties":false},"ResolvedEnvVarResponse":{"type":"object","description":"One entry in the computed env-var view that merges manual and integration\nsources and tags each result with its origin. `value_preview` is always\nmasked — plaintext must be fetched per-key via the existing reveal endpoint,\nwhich is audit-logged.","required":["key","value_preview","source","environments","include_in_preview"],"properties":{"environments":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentInfo"},"description":"Environments this var applies to. For integration-sourced vars this\nreflects every environment of the project (integrations are global)."},"include_in_preview":{"type":"boolean","description":"Whether the var would be auto-applied to preview environments.\nIntegration vars always surface in preview; manual vars follow the flag."},"key":{"type":"string"},"source":{"$ref":"#/components/schemas/ResolvedEnvVarSource"},"value_preview":{"type":"string","description":"Masked or truncated preview. Never the raw value."}}},"ResolvedEnvVarSource":{"oneOf":[{"type":"object","description":"Manually-defined env var. If `overrides_service` is set, this key would\notherwise have been supplied by an integration — the UI should show the\nintegration icon plus an \"overridden\" indicator.","required":["var_id","type"],"properties":{"overrides_service":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/EnvVarIntegrationInfo"}]},"type":{"type":"string","enum":["manual"]},"var_id":{"type":"integer","format":"int32"}}},{"type":"object","description":"Supplied by a linked external service (Postgres, Redis, S3, etc.).","required":["service","type"],"properties":{"service":{"$ref":"#/components/schemas/EnvVarIntegrationInfo"},"type":{"type":"string","enum":["integration"]}}}],"description":"Where a resolved env var comes from. Integration-sourced vars may be\n\"shadowed\" by a manual entry with the same key, in which case the response\ncarries `Manual` with `overrides_service` populated so the UI can still show\nthe integration icon."},"ResourceCounts":{"type":"object","description":"Quick count of resources involved in the migration","required":["projects","environments","deployments","environment_variables","services","domains"],"properties":{"deployments":{"type":"integer","minimum":0},"domains":{"type":"integer","minimum":0},"environment_variables":{"type":"integer","minimum":0},"environments":{"type":"integer","minimum":0},"projects":{"type":"integer","minimum":0},"services":{"type":"integer","minimum":0}}},"ResourceFootprint":{"type":"object","description":"A CPU + memory footprint (requests or measured usage)","required":["cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"CPU in millicores"},"memory_mb":{"type":"integer","format":"int64","description":"Memory in MB"}}},"ResourceInfo":{"type":"object","description":"Resource attributes extracted from OTel resource descriptors.","required":["service_name","attributes"],"properties":{"attributes":{"type":"object"},"deployment_environment":{"type":["string","null"]},"service_name":{"type":"string"},"service_version":{"type":["string","null"]}}},"ResourceLimitApplyResult":{"type":"object","description":"Per-container outcome of a live `docker update` call. Surfaced from the\nPATCH /resources endpoint so the UI can tell the operator whether the\nnew caps are already in effect or whether they only apply on next\nrecreate (e.g., container was missing).","required":["role","container_name","outcome"],"properties":{"container_name":{"type":"string"},"error":{"type":["string","null"],"description":"Populated only when `outcome == \"failed\"`."},"outcome":{"type":"string","description":"One of:\n- \"applied\" — Docker accepted the update; caps are live now.\n- \"missing\" — container does not exist; caps stored, will apply on next start.\n- \"stopped\" — container exists but isn't running; Docker still\n accepts the update (the new caps apply on next start).\n- \"failed\" — `docker update` returned an error (see `error`)."},"role":{"type":"string","description":"`service_members.role` for cluster members; \"standalone\" otherwise."}}},"ResourceLimits":{"type":"object","description":"Resource limits and requests","properties":{"cpu_limit":{"type":["integer","null"],"format":"int32","description":"CPU limit (millicores)"},"cpu_request":{"type":["integer","null"],"format":"int32","description":"CPU request (millicores)"},"memory_limit":{"type":["integer","null"],"format":"int32","description":"Memory limit (MB)"},"memory_request":{"type":["integer","null"],"format":"int32","description":"Memory request (MB)"}}},"ResourceLimitsResponse":{"type":"object","description":"Container resource limits","properties":{"cpu_limit":{"type":["integer","null"],"format":"int32"},"cpu_request":{"type":["integer","null"],"format":"int32"},"memory_limit":{"type":["integer","null"],"format":"int32"},"memory_request":{"type":["integer","null"],"format":"int32"}}},"ResourceLimitsUpdateResponse":{"type":"object","description":"Response from PATCH /external-services/{id}/resources.","required":["limits","applied"],"properties":{"applied":{"type":"array","items":{"$ref":"#/components/schemas/ResourceLimitApplyResult"},"description":"Per-container result of trying to apply the limits live."},"limits":{"$ref":"#/components/schemas/ServiceResourceLimits","description":"The limits that were persisted to the encrypted config."}}},"ResourcesBody":{"type":"object","description":"Nested `resources: { memory, vcpus }` as sent by `@vercel/sandbox`.\n`memory` is in MB, `vcpus` is fractional CPU count.","properties":{"memory":{"type":["integer","null"],"format":"int64","minimum":0},"vcpus":{"type":["number","null"],"format":"double"}}},"RestoreCapabilities":{"type":"object","description":"Capabilities a service exposes for the generic restore framework.\n\nEach engine overrides `ExternalService::restore_capabilities` to declare\nwhat it supports. The handler layer uses this to validate requests and\nthe UI uses it to conditionally show options (e.g., PITR picker).","required":["restore_in_place","restore_to_new_service","pitr"],"properties":{"earliest_pitr_time":{"type":["string","null"],"format":"date-time","description":"Earliest recoverable timestamp, if `pitr` is true. Derived from\nengine-specific archive metadata (e.g., `pg_stat_archiver`)."},"latest_pitr_time":{"type":["string","null"],"format":"date-time","description":"Latest recoverable timestamp, if `pitr` is true."},"pitr":{"type":"boolean","description":"Point-in-time recovery using engine-specific continuous archives\n(WAL for Postgres, AOF for Redis, oplog for MongoDB, object versions for S3)."},"restore_in_place":{"type":"boolean","description":"Restore a backup onto the same running service (destructive)."},"restore_to_new_service":{"type":"boolean","description":"Restore a backup into a freshly provisioned service."}}},"RestoreCapabilitiesResponse":{"allOf":[{"$ref":"#/components/schemas/RestoreCapabilities","description":"Trait-declared capabilities."},{"type":"object","required":["suggested_new_service_name"],"properties":{"suggested_new_service_name":{"type":"string","description":"Suggested name for the new service when creating a clone. Safe to\npre-fill into the UI dialog; the user can edit before submitting."}}}]},"RestorePlan":{"type":"object","description":"Preview of a restore operation. Answers \"what will happen if I click\nstart?\" with engine-level specificity so the user can confirm before\ncommitting to a destructive action.","required":["engine","target_service","source_backup","strategy","steps","warnings","errors","destructive","mode"],"properties":{"destructive":{"type":"boolean","description":"Whether any step overwrites existing data on the target service."},"engine":{"type":"string","description":"Target engine (\"postgres\", etc.)."},"errors":{"type":"array","items":{"type":"string"},"description":"Blocking problems. The UI disables the Start button when non-empty."},"mode":{"type":"string","description":"Echo of the requested mode for the UI."},"source_backup":{"$ref":"#/components/schemas/PlanSourceBackup","description":"Backup we'll read from."},"steps":{"type":"array","items":{"type":"string"},"description":"Ordered list of human-readable actions the orchestrator will take."},"strategy":{"type":"string","description":"How the restore will be performed: \"walg_restore\", \"pg_dump_restore\",\nor \"unsupported\"."},"target_service":{"$ref":"#/components/schemas/PlanTarget","description":"Service we'll operate on (or provision a sibling of)."},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking caveats the user should see (cross-service, empty\nlocation that will be auto-resolved, missing engine metadata, ...)."}}},"RestoreRequestMode":{"oneOf":[{"type":"object","description":"Restore the backup onto the existing service (destructive).","required":["mode"],"properties":{"mode":{"type":"string","enum":["in_place"]}}},{"type":"object","description":"Provision a new service and restore into it.","required":["name","mode"],"properties":{"mode":{"type":"string","enum":["new_service"]},"name":{"type":"string","description":"Name for the new service. Orchestrator auto-suggests\n`{source}-restore-{yyyymmdd-hhmm}` if caller omits, but we require\nan explicit value at the API boundary."},"parameter_overrides":{"description":"Optional parameter overrides (port, docker_image, database)."}}},{"type":"object","description":"Point-in-time recovery. Only valid on WAL-G backups (Postgres).","required":["to_new_service","target","mode"],"properties":{"mode":{"type":"string","enum":["pitr"]},"new_service_name":{"type":["string","null"],"description":"Required when `to_new_service` is true."},"target":{"$ref":"#/components/schemas/RecoveryTarget","description":"Recovery target kind + value."},"to_new_service":{"type":"boolean","description":"Whether PITR restores in place or creates a new service."}}}],"description":"What the caller wants to do. Mirrors `externalsvc::RestoreMode` but\nflattened for JSON over the wire."},"RestoreRunView":{"type":"object","required":["id","source_backup_id","source_service_id","mode","status","phase","created_at"],"properties":{"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"finished_at":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mode":{"type":"string"},"phase":{"type":"string"},"recovery_target":{},"source_backup_id":{"type":"integer","format":"int32"},"source_service_id":{"type":"integer","format":"int32"},"started_at":{"type":["string","null"]},"status":{"type":"string"},"target_service_id":{"type":["integer","null"],"format":"int32"},"target_service_name":{"type":["string","null"]}}},"RetentionCleanupFailure":{"type":"object","required":["backup_id","reason","partial","deleted_objects"],"properties":{"backup_id":{"type":"string"},"deleted_objects":{"type":"integer","format":"int64","minimum":0},"partial":{"type":"boolean"},"reason":{"type":"string"}}},"RetentionCleanupReport":{"type":"object","required":["dry_run","expired","deleted","failed","failures","deleted_backup_ids","deleted_backup_ids_truncated","partially_deleted_backup_ids","partially_deleted_backup_ids_truncated","candidate_backup_ids","candidate_backup_ids_truncated"],"properties":{"candidate_backup_ids":{"type":"array","items":{"type":"string"},"description":"Capped sample of backups selected by the retention policy."},"candidate_backup_ids_truncated":{"type":"boolean"},"deleted":{"type":"integer","format":"int64","minimum":0},"deleted_backup_ids":{"type":"array","items":{"type":"string"},"description":"Capped sample of deleted backup UUIDs for audit attribution."},"deleted_backup_ids_truncated":{"type":"boolean"},"dry_run":{"type":"boolean","description":"True when this report is a non-destructive preview."},"expired":{"type":"integer","format":"int64","minimum":0},"failed":{"type":"integer","format":"int64","minimum":0},"failures":{"type":"array","items":{"$ref":"#/components/schemas/RetentionCleanupFailure"},"description":"Capped diagnostic sample; `failed` remains the authoritative total."},"partially_deleted_backup_ids":{"type":"array","items":{"type":"string"}},"partially_deleted_backup_ids_truncated":{"type":"boolean"},"schedule_id":{"type":["integer","null"],"format":"int32","description":"Schedule scope, or `None` when every schedule was considered."}}},"RetryClusterRequest":{"type":"object","description":"Request body for retrying a failed cluster initialization.","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberRequest"},"description":"Cluster member specifications (same format as create).\nIf omitted, the original member configuration is reconstructed from\nthe preserved service_members records."}}},"RevenueRow":{"type":"object","required":["id","ts","provider","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"provider":{"type":"string"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"RiskLevel":{"type":"string","description":"Risk level for a migration step","enum":["none","low","medium","high","critical"]},"RoleInfo":{"type":"object","description":"Information about a role","required":["name","description","permissions"],"properties":{"description":{"type":"string","description":"Human-readable description of the role"},"name":{"type":"string","description":"The role identifier (e.g., \"admin\")"},"permissions":{"type":"array","items":{"type":"string"},"description":"Permissions included in this role"}}},"RootfsCacheEntry":{"type":"object","description":"A cached rootfs image (Firecracker backend). Digest-keyed build artifact\nshared by all VMs created from the same image.","required":["digest","bytes","referenced_by"],"properties":{"bytes":{"type":"integer","format":"int64","description":"Actual on-disk size in bytes (sparse-aware).","minimum":0},"digest":{"type":"string","description":"Image digest this rootfs was built from (the cache key)."},"referenced_by":{"type":"array","items":{"type":"string"},"description":"IDs of live sandboxes whose per-VM disk was cloned from this entry.\nEmpty means the entry is reclaimable — no sandbox needs it."}}},"RootfsGcReport":{"type":"object","description":"Outcome of a rootfs garbage-collection pass.","required":["removed_digests","freed_bytes"],"properties":{"freed_bytes":{"type":"integer","format":"int64","minimum":0},"removed_digests":{"type":"array","items":{"type":"string"},"description":"Digests of cache entries removed because no sandbox referenced them."}}},"RootfsReport":{"type":"object","description":"Snapshot of a backend's rootfs storage for the management API. Backends\nwithout a rootfs concept (Docker, local) return an empty report.","required":["cache_bytes","cache","vm_bytes","vms"],"properties":{"cache":{"type":"array","items":{"$ref":"#/components/schemas/RootfsCacheEntry"}},"cache_bytes":{"type":"integer","format":"int64","minimum":0},"vm_bytes":{"type":"integer","format":"int64","minimum":0},"vms":{"type":"array","items":{"$ref":"#/components/schemas/RootfsVmEntry"}}}},"RootfsVmEntry":{"type":"object","description":"A per-sandbox rootfs disk (Firecracker backend). One per non-destroyed\nsandbox — the authoritative storage, independent of the cache.","required":["sandbox_name","bytes","running"],"properties":{"bytes":{"type":"integer","format":"int64","minimum":0},"running":{"type":"boolean"},"sandbox_name":{"type":"string"}}},"RouteRefreshResponse":{"type":"object","required":["route_count","message"],"properties":{"message":{"type":"string","description":"Human-readable message"},"route_count":{"type":"integer","description":"Number of routes loaded","minimum":0}}},"RouteResponse":{"type":"object","required":["id","domain","host","port","enabled","route_type","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"enabled":{"type":"boolean"},"host":{"type":"string"},"id":{"type":"integer","format":"int32"},"port":{"type":"integer","format":"int32"},"route_type":{"type":"string","description":"Route type: \"http\" or \"tls\""},"updated_at":{"type":"integer","format":"int64"}}},"RouteRole":{"type":"object","required":["id","name","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64","example":"1683900000000"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"updated_at":{"type":"integer","format":"int64","example":"1683900000000"}}},"RouteUser":{"type":"object","required":["id","name","username","email","image","mfa_enabled","email_verified","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64","example":"1683900000000"},"deleted_at":{"type":["integer","null"],"format":"int64"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"image":{"type":"string"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"integer","format":"int64","example":"1683900000000"},"username":{"type":"string"}}},"RouteUserWithRoles":{"type":"object","required":["user","roles"],"properties":{"roles":{"type":"array","items":{"$ref":"#/components/schemas/RouteRole"}},"user":{"$ref":"#/components/schemas/RouteUser"}}},"RunBackupRequest":{"type":"object","required":["backup_type"],"properties":{"backup_type":{"type":"string","description":"Type of backup to perform","example":"full"}}},"RunExternalServiceBackupRequest":{"type":"object","properties":{"backup_type":{"type":["string","null"],"description":"Type of backup to perform (e.g., \"full\", \"incremental\")","example":"full"},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"ID of the S3 source to store the backup. If omitted, the current default S3 source is used.","example":1}}},"S3ConnectionTestResponse":{"type":"object","description":"Response body for an S3 connection test.","required":["ok","message"],"properties":{"message":{"type":"string","description":"Human-readable message (success confirmation or error detail)."},"ok":{"type":"boolean","description":"Whether the connection and credentials worked."}}},"S3CredentialsResponse":{"type":"object","description":"S3 credentials distributed to agents for backup/restore operations.","required":["access_key_id","secret_key","region","bucket_name","force_path_style"],"properties":{"access_key_id":{"type":"string"},"bucket_name":{"type":"string"},"endpoint":{"type":["string","null"]},"force_path_style":{"type":"boolean"},"region":{"type":"string"},"secret_key":{"type":"string"}}},"S3SourceResponse":{"type":"object","description":"Response type for S3 source","required":["id","name","bucket_name","bucket_path","access_key_id","secret_key","region","is_default","created_at","updated_at"],"properties":{"access_key_id":{"type":"string","example":"AKIAXXXXXXXXXXXXXXXX"},"bucket_name":{"type":"string"},"bucket_path":{"type":"string"},"created_at":{"type":"integer","format":"int64"},"endpoint":{"type":["string","null"],"example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"]},"id":{"type":"integer","format":"int32"},"is_default":{"type":"boolean"},"name":{"type":"string"},"region":{"type":"string"},"secret_key":{"type":"string","writeOnly":true},"updated_at":{"type":"integer","format":"int64"}}},"SandboxDomainResponse":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}},"SandboxEvent":{"type":"object","description":"One entry in a sandbox's operations timeline.","required":["event_type","at"],"properties":{"at":{"type":"integer","format":"int64","description":"Unix epoch milliseconds."},"detail":{"description":"Optional structured context (shape depends on `event_type`)."},"event_type":{"type":"string","description":"Machine-readable operation (`created`, `stopped`, `resumed`,\n`restarted`, `timeout_extended`, `resized`, `preview_password_set`,\n`preview_password_cleared`, `source_seeded`, `destroyed`)."}}},"SandboxEventsResponse":{"type":"object","required":["events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SandboxEvent"}}}},"SandboxInner":{"type":"object","description":"Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —\nthe SDK's zod validator rejects missing required fields.","required":["id","memory","vcpus","region","runtime","timeout","status","requestedAt","createdAt","updatedAt","cwd","name","preview_url_template"],"properties":{"agent_run_id":{"type":["integer","null"],"format":"int32","description":"Agent run this sandbox executes (autofixer / workflow agent).\n`None` for sandboxes created via this API."},"backend":{"type":["string","null"],"description":"Isolation backend: \"docker\" | \"firecracker\". `None` on legacy rows\ncreated before the backend was recorded."},"createdAt":{"type":"integer","format":"int64"},"cwd":{"type":"string"},"disk_size_mb":{"type":["integer","null"],"format":"int64","description":"Configured root disk size in MB (Firecracker). `None` when unknown or\nthe default.","minimum":0},"id":{"type":"string"},"image":{"type":["string","null"]},"memory":{"type":"integer","format":"int64","minimum":0},"name":{"type":"string"},"preview_password_hint":{"type":["string","null"]},"preview_url_template":{"type":"string"},"region":{"type":"string"},"requestedAt":{"type":"integer","format":"int64","description":"Creation time as Unix epoch milliseconds."},"runtime":{"type":"string"},"status":{"type":"string"},"timeout":{"type":"integer","format":"int64","description":"Idle timeout in milliseconds (SDK convention).","minimum":0},"updatedAt":{"type":"integer","format":"int64"},"vcpus":{"type":"number","format":"double"}}},"SandboxResponse":{"type":"object","description":"`@vercel/sandbox` wraps every single-sandbox response as\n`{ sandbox: {...}, routes: [...] }`. The SDK reads both.","required":["sandbox","routes"],"properties":{"routes":{"type":"array","items":{"$ref":"#/components/schemas/SandboxRoute"}},"sandbox":{"$ref":"#/components/schemas/SandboxInner"}}},"SandboxRoute":{"type":"object","description":"A single preview route, one per declared port. We don't know ports\nupfront, so we surface an empty array by default — SDK clients use\ntheir own port when calling `sandbox.domain(port)`.","required":["url","subdomain","port"],"properties":{"port":{"type":"integer","format":"int32","minimum":0},"subdomain":{"type":"string"},"url":{"type":"string"}}},"SandboxStatusResponse":{"type":"object","required":["docker_available","image_ready","image_name","firecracker_available"],"properties":{"docker_available":{"type":"boolean"},"error":{"type":["string","null"]},"firecracker_available":{"type":"boolean"},"image_name":{"type":"string"},"image_ready":{"type":"boolean"}}},"SaveAgentTokenRequest":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"The OAuth token from `claude setup-token` or an API key.\nWill be encrypted before storage."}}},"SaveAgentTokenResponse":{"type":"object","required":["saved"],"properties":{"saved":{"type":"boolean"}}},"SaveCredentialRequest":{"type":"object","required":["auth_type","credential"],"properties":{"auth_type":{"type":"string","description":"Auth flavor id (must match one of the provider's catalog entries)."},"credential":{"type":"string","description":"Plaintext credential body (API key, OAuth token, or full config file\ncontents). Encrypted with `EncryptionService` before being persisted\ninside the `agent_sandbox.providers` JSON map."}}},"SaveCredentialResponse":{"type":"object","required":["saved","provider_id","auth_type"],"properties":{"auth_type":{"type":"string"},"provider_id":{"type":"string"},"saved":{"type":"boolean"}}},"ScalewayCredentialsRequest":{"type":"object","required":["api_key","project_id"],"properties":{"api_key":{"type":"string","example":"scw-secret-key-12345"},"project_id":{"type":"string","example":"12345678-1234-1234-1234-123456789012"}}},"ScanResponse":{"type":"object","required":["id","project_id","scanner_type","status","total_count","critical_count","high_count","medium_count","low_count","unknown_count","started_at","created_at","updated_at"],"properties":{"branch":{"type":["string","null"]},"commit_hash":{"type":["string","null"]},"completed_at":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"created_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"critical_count":{"type":"integer","format":"int32"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"high_count":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"low_count":{"type":"integer","format":"int32"},"medium_count":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"scanner_type":{"type":"string"},"scanner_version":{"type":["string","null"]},"started_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"status":{"type":"string"},"total_count":{"type":"integer","format":"int32"},"unknown_count":{"type":"integer","format":"int32"},"updated_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"}}},"ScheduleRunEntry":{"type":"object","description":"A single run-history entry for the schedule detail page (deliverable 1).\n\nCombines one `backups` row with the most-recent `backup_jobs` row for that\nbackup via a lateral JOIN. Fields from `backup_jobs` are `None` for legacy\nbackup rows that pre-date ADR-014.","required":["backup_id","backup_uuid","state","started_at","s3_location"],"properties":{"attempts":{"type":["integer","null"],"format":"int32","description":"Number of claim-and-run attempts so far. `None` for legacy rows."},"backup_id":{"type":"integer","format":"int32","description":"DB id of the `backups` row."},"backup_uuid":{"type":"string","description":"UUID string (`backups.backup_id`)."},"current_step":{"type":["string","null"],"description":"Last completed step reported by the engine (e.g. `\"upload\"`).\n`None` when no step has been persisted yet."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When the backup finished, if known."},"job_id":{"type":["integer","null"],"format":"int64","description":"Most recent `backup_jobs.id` for this backup. `None` for legacy rows."},"s3_location":{"type":"string","description":"S3 object key or URL where the backup data lives."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Final size in bytes once completed. `None` while running."},"started_at":{"type":"string","description":"When the backup was started (ISO 8601 / RFC 3339)."},"state":{"type":"string","description":"Current state: `\"pending\"`, `\"running\"`, `\"completed\"`, `\"failed\"`."}}},"ScheduleRunJobEntry":{"type":"object","description":"A single job entry inside an expanded schedule run, returned by\n[`BackupService::list_schedule_run_jobs`].","required":["backup_id","backup_uuid","engine","service_name","state","started_at","s3_source_id"],"properties":{"backup_id":{"type":"integer","format":"int32","description":"`backups.id` for this job."},"backup_uuid":{"type":"string","description":"`backups.backup_id` UUID string."},"engine":{"type":"string","description":"Engine key (e.g. `\"control_plane\"`, `\"redis\"`)."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When this child backup finished, if known."},"s3_source_id":{"type":"integer","format":"int32","description":"FK to `s3_sources.id` — needed for the backup detail link."},"service_id":{"type":["integer","null"],"format":"int32","description":"`external_services.id` — `NULL` for the control-plane job."},"service_name":{"type":"string","description":"Name of the external service, or `\"control plane\"` for the\ncontrol-plane job."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes once completed; `None` while running."},"started_at":{"type":"string","description":"When this child backup started (ISO 8601 / RFC 3339)."},"state":{"type":"string","description":"Current state of this child backup."}}},"ScheduleRunListResponse":{"type":"object","description":"Paginated run-history response for a backup schedule (deliverable 1).","required":["runs","total","page","page_size"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page (clamped to 1–100)."},"runs":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunEntry"},"description":"Run entries, newest first."},"total":{"type":"integer","format":"int64","description":"Total number of runs across all pages."}}},"ScheduleRunResponse":{"type":"object","description":"HTTP response body for `POST /api/backups/schedules/{id}/run` (fan-out).","required":["schedule_run_id","jobs"],"properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/EnqueuedJob"},"description":"All jobs that were enqueued in this fan-out."},"schedule_run_id":{"type":"integer","format":"int64","description":"The `schedule_runs.id` of the newly created run."}}},"ScheduleRunSummary":{"type":"object","description":"Summary of one scheduler tick (or one \"Run now\" click), returned by\n[`BackupService::list_schedule_runs`].\n\nThe `aggregate_state` is computed at read time from child backup counts:\n- `\"running\"` — at least one child is `\"pending\"` or `\"running\"`.\n- `\"failed\"` — at least one child is `\"failed\"` and none are running.\n- `\"completed\"` — all children are `\"completed\"`.","required":["run_id","schedule_id","triggered_by","started_at","aggregate_state","total_jobs","completed_jobs","failed_jobs","running_jobs","pending_jobs"],"properties":{"aggregate_state":{"type":"string","description":"Aggregate state computed from child counts (see struct docs)."},"completed_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"completed\"`."},"failed_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When all children reached a terminal state. `None` while any child is\nstill `\"pending\"` or `\"running\"`."},"pending_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"pending\"`."},"run_id":{"type":"integer","format":"int64","description":"`schedule_runs.id` for this tick."},"running_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"running\"`."},"schedule_id":{"type":"integer","format":"int32","description":"FK to `backup_schedules.id`."},"started_at":{"type":"string","description":"When the fan-out started (ISO 8601 / RFC 3339)."},"total_jobs":{"type":"integer","format":"int64","description":"Total number of child backup jobs in this run."},"triggered_by":{"type":"string","description":"How the run was triggered: `\"cron\"` or `\"manual\"`."}}},"ScheduleRunSummaryList":{"type":"object","description":"Paginated list of schedule run summaries returned by the new\n[`BackupService::list_schedule_runs`].","required":["runs","total","page","page_size"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page."},"runs":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunSummary"},"description":"Run summaries, newest first. Includes synthetic single-job rows for\nlegacy `backups` rows that have `schedule_id` set but no\n`schedule_run_id` (pre-fan-out history)."},"total":{"type":"integer","format":"int64","description":"Total number of run entries across all pages."}}},"ScreenshotSettings":{"type":"object","properties":{"enabled":{"type":"boolean","default":false},"provider":{"type":"string","default":"local"},"url":{"type":"string","default":""}}},"SearchLogsRequest":{"type":"object","required":["project_id"],"properties":{"container_ids":{"type":"array","items":{"type":"string"},"description":"Filter to specific containers (Docker container IDs). Empty = all\ncontainers. Drives \"filter by container / show all\" in a project's\nhistory, which spans multiple deployments and containers."},"context_lines":{"type":["integer","null"],"format":"int32","description":"grep -C: number of raw context lines to include before and after each\nmatch (0 = none, default). Clamped to 50 server-side. The surrounding\nlines ignore the level/text filters — they are the actual adjacent log\nlines, merged across overlapping matches.","minimum":0},"cursor":{"type":["string","null"],"description":"Pagination cursor"},"deploy_id":{"type":["integer","null"],"format":"int32","description":"Filter by deployment ID (deployments.id)"},"end_time":{"type":["string","null"],"description":"End of time range (ISO 8601). Defaults to now."},"envs":{"type":"array","items":{"type":"string"},"description":"Filter by environments"},"external_service_id":{"type":["integer","null"],"format":"int32","description":"When set, search an imported/managed external service's logs instead\nof a project's. `project_id` is ignored in this mode."},"levels":{"type":"array","items":{"type":"string"},"description":"Filter by log levels"},"node_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"Filter to specific worker nodes (node_id). Empty = all nodes, including\ncontrol-plane-local logs."},"page_size":{"type":["integer","null"],"format":"int32","description":"Page size (default: 100, max: 500)","minimum":0},"project_id":{"type":"integer","format":"int32","description":"Project ID (integer, as used by the rest of the platform)"},"services":{"type":"array","items":{"type":"string"},"description":"Filter by services"},"start_time":{"type":["string","null"],"description":"Start of time range (ISO 8601). Defaults to 1 hour ago."},"text":{"type":["string","null"],"description":"Full text search query"}}},"SearchLogsResponse":{"type":"object","required":["lines","search_mode","total_scanned"],"properties":{"available_sources":{"type":"array","items":{"$ref":"#/components/schemas/LogSource"},"description":"Distinct containers/nodes/services available in the queried scope, for\nthe filter dropdowns. Populated on the first page (no cursor)."},"lines":{"type":"array","items":{"$ref":"#/components/schemas/LogSearchLine"}},"next_cursor":{"type":["string","null"]},"search_mode":{"$ref":"#/components/schemas/SearchMode"},"total_scanned":{"type":"integer","format":"int64","minimum":0}}},"SearchMode":{"type":"string","description":"Search execution mode","enum":["index","archive"]},"Seasonality":{"type":"string","description":"Seasonality model for an anomaly baseline.","enum":["none","hourly","daily","weekly"]},"SecretResponse":{"type":"object","required":["id","name","secret_type","value","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mount_path":{"type":["string","null"]},"name":{"type":"string"},"secret_type":{"type":"string"},"updated_at":{"type":"string"},"value":{"type":"string","description":"Always masked in responses"}}},"SecurityConfig":{"type":"object","description":"Security configuration for projects and environments\n\nThis configuration can be set at three levels:\n1. Global (in settings table) - applies to all projects\n2. Project level - overrides global settings for specific project\n3. Environment level - overrides project settings for specific environment\n\nThe inheritance chain: Environment > Project > Global","properties":{"attackMode":{"type":["string","null"],"description":"Attack mode configuration (future: \"off\", \"challenge\", \"block\")\nPlaceholder for DDoS protection, bot detection, etc."},"challengeConfig":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeConfig","description":"Challenge configuration (future: CAPTCHA, JS challenge, etc.)"}]},"enabled":{"type":["boolean","null"],"description":"Enable/disable security features at this level\nIf None, inherits from parent level"},"geoRestrictions":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GeoRestrictionsConfig","description":"Geographic restrictions (future: country blocking, etc.)"}]},"headers":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityHeadersConfig","description":"Security headers configuration"}]},"passwordProtection":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PasswordProtectionConfig","description":"Password protection: shows an HTML password form before allowing access"}]},"rateLimiting":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RateLimitConfig","description":"Rate limiting configuration"}]}}},"SecurityHeadersConfig":{"type":"object","description":"Security headers configuration (subset of global SecurityHeadersSettings)","properties":{"contentSecurityPolicy":{"type":["string","null"],"description":"Custom CSP (only used if preset is \"custom\")"},"preset":{"type":["string","null"],"description":"Use a preset: \"strict\", \"moderate\", \"permissive\", \"disabled\", \"custom\""},"referrerPolicy":{"type":["string","null"],"description":"Referrer-Policy override"},"strictTransportSecurity":{"type":["string","null"],"description":"HSTS override"},"xFrameOptions":{"type":["string","null"],"description":"X-Frame-Options override"}}},"SecurityHeadersSettings":{"type":"object","properties":{"content_security_policy":{"type":["string","null"],"default":"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'"},"enabled":{"type":"boolean","default":false},"permissions_policy":{"type":["string","null"],"default":"geolocation=(), microphone=(), camera=()"},"preset":{"type":"string","default":"moderate"},"referrer_policy":{"type":"string","default":"strict-origin-when-cross-origin"},"strict_transport_security":{"type":"string","default":"max-age=31536000; includeSubDomains"},"x_content_type_options":{"type":"string","default":"nosniff"},"x_frame_options":{"type":"string","default":"SAMEORIGIN"},"x_xss_protection":{"type":"string","default":"1; mode=block"}}},"SendEmailRequestBody":{"type":"object","required":["from","to","subject"],"properties":{"bcc":{"type":["array","null"],"items":{"type":"string"},"description":"BCC recipients"},"cc":{"type":["array","null"],"items":{"type":"string"},"description":"CC recipients"},"from":{"type":"string","description":"Sender email address (domain will be auto-extracted for lookup)","example":"hello@updates.example.com"},"from_name":{"type":["string","null"],"description":"Sender display name","example":"My App"},"headers":{"type":["object","null"],"description":"Custom headers","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"html":{"type":["string","null"],"description":"HTML body content","example":"

Hello World

"},"reply_to":{"type":["string","null"],"description":"Reply-to address"},"subject":{"type":"string","description":"Email subject","example":"Welcome to our platform!"},"tags":{"type":["array","null"],"items":{"type":"string"},"description":"Tags for categorization","example":["welcome","onboarding"]},"text":{"type":["string","null"],"description":"Plain text body content","example":"Hello World"},"to":{"type":"array","items":{"type":"string"},"description":"Recipient email addresses","example":["user@example.com"]},"track_clicks":{"type":["boolean","null"],"description":"Enable click tracking (link rewriting). Defaults to false."},"track_opens":{"type":["boolean","null"],"description":"Enable open tracking (tracking pixel injection). Defaults to false."}}},"SendEmailResponseBody":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","description":"Email ID","example":"550e8400-e29b-41d4-a716-446655440000"},"provider_message_id":{"type":["string","null"],"description":"Provider message ID"},"status":{"type":"string","description":"Email status","example":"sent"}}},"SendMessageRequest":{"type":"object","required":["content"],"properties":{"content":{"type":"string"},"page_context":{"type":["string","null"],"description":"Optional, client-supplied description of the page/entity the user is\ncurrently viewing (e.g. a trace in a project). Injected into the model's\nview of this turn only — never stored or shown in history. Capped server\nside; oversized values are ignored rather than rejected."}}},"SensitiveConfigValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SensitiveMcpConfigValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SensitiveValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SentryChunkUploadResponse":{"type":"object","required":["url","chunkSize","chunksPerRequest","maxFileSize","maxRequestSize","concurrency","hashAlgorithm","compression","accept"],"properties":{"accept":{"type":"array","items":{"type":"string"}},"chunkSize":{"type":"integer","format":"int64","minimum":0},"chunksPerRequest":{"type":"integer","format":"int32","minimum":0},"compression":{"type":"array","items":{"type":"string"}},"concurrency":{"type":"integer","format":"int32","minimum":0},"hashAlgorithm":{"type":"string"},"maxFileSize":{"type":"integer","format":"int64","minimum":0},"maxRequestSize":{"type":"integer","format":"int64","minimum":0},"url":{"type":"string"}}},"SentryCreateReleaseRequest":{"type":"object","required":["version"],"properties":{"projects":{"type":"array","items":{"type":"string"},"description":"Project slugs this release belongs to"},"version":{"type":"string","description":"Release version identifier"}}},"SentryEventRequest":{"type":"object","properties":{"event_id":{"type":["string","null"]},"message":{"type":["string","null"]},"platform":{"type":["string","null"]},"timestamp":{"type":["string","null"]}}},"SentryEventResponse":{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}},"SentryReleaseFileResponse":{"type":"object","required":["id","name","headers","size","sha1","dateCreated"],"properties":{"dateCreated":{"type":"string"},"dist":{"type":["string","null"]},"headers":{},"id":{"type":"string"},"name":{"type":"string"},"sha1":{"type":"string"},"size":{"type":"integer","format":"int64"}}},"SentryReleaseProjectRef":{"type":"object","required":["name","slug"],"properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"SentryReleaseResponse":{"type":"object","required":["version","dateCreated","shortVersion","projects"],"properties":{"dateCreated":{"type":"string"},"dateReleased":{"type":["string","null"]},"projects":{"type":"array","items":{"$ref":"#/components/schemas/SentryReleaseProjectRef"}},"shortVersion":{"type":"string"},"version":{"type":"string"}}},"SeriesStateEntry":{"type":"object","description":"One series' persisted state snapshot for a dynamic rule (ADR-026 follow-up):\nthe state after the latest tick, the value evaluated this tick, and the open\nalarm id (when firing). Serialized into the `series_states` jsonb column keyed\nby the human-readable [`series_label`]; the alert response decodes it back.","required":["state","value"],"properties":{"alarm_id":{"type":["integer","null"],"format":"int32","description":"The open alarm's id when the series is firing; `null` when ok."},"state":{"type":"string","description":"`firing` or `ok` for this series after the latest tick."},"value":{"type":"number","format":"double","description":"The value the rule evaluated for this series this tick."}}},"ServiceAccessInfo":{"type":"object","description":"Response containing information about how the service is being accessed","required":["access_mode","can_create_domains"],"properties":{"access_mode":{"type":"string","description":"Mode of access: \"local\", \"direct\", \"nat\", or \"cloudflare_tunnel\""},"can_create_domains":{"type":"boolean","description":"Whether domain creation is allowed in this mode"},"domain_creation_error":{"type":["string","null"],"description":"Error message if domain creation is not allowed"},"private_ip":{"type":["string","null"],"description":"Server's private/local IP address (always returned if available)"},"public_ip":{"type":["string","null"],"description":"Server's public IP address (always returned if available)"}}},"ServiceAction":{"type":"string","description":"What to do with a service during migration","enum":["create","link-external","skip"]},"ServiceAlertRuleResponse":{"type":"object","description":"Wire representation of a monitoring alert rule.\n\nRegistered under a domain-prefixed OpenAPI schema name to avoid colliding\nwith `temps-error-tracking`'s unrelated `AlertRuleResponse` (utoipa keys\nschemas by their bare struct name, so without `as = ...` the last crate to\nregister would silently shadow this one in the merged spec / generated SDK).","required":["id","name","metric_name","threshold","comparator","severity","for_duration_secs","enabled"],"properties":{"comparator":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"metric_name":{"type":"string"},"name":{"type":"string"},"service_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"silenced_until":{"type":["string","null"]},"threshold":{"type":"number","format":"double"}}},"ServiceBackupEntryResponse":{"type":"object","description":"A single backup entry in the per-service backup list.","required":["id","backup_id","name","state","backup_type","started_at","s3_location","compression_type","s3_source_id","s3_source_name","external_service_backup_id"],"properties":{"backup_id":{"type":"string","description":"UUID string assigned at backup creation time."},"backup_type":{"type":"string","description":"Backup variant (e.g. \"full\", \"incremental\")."},"compression_type":{"type":"string","description":"Compression algorithm used (e.g. \"gzip\")."},"error_message":{"type":["string","null"],"description":"Engine-reported error message, populated when `state = \"failed\"`."},"external_service_backup_id":{"type":"integer","format":"int32","description":"Row ID from `external_service_backups`."},"finished_at":{"type":["string","null"],"description":"ISO 8601 timestamp when the backup finished, if known.","example":"2025-01-15T14:35:00Z"},"id":{"type":"integer","format":"int32","description":"Row ID from the `backups` table."},"name":{"type":"string","description":"Human-friendly display name."},"s3_location":{"type":"string","description":"Object key or `s3://` URL for the backup data."},"s3_source_id":{"type":"integer","format":"int32","description":"FK to `s3_sources.id`."},"s3_source_name":{"type":"string","description":"Human-readable name of the S3 source."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the backup in bytes, if available."},"started_at":{"type":"string","description":"ISO 8601 timestamp when the backup started.","example":"2025-01-15T14:30:00Z"},"state":{"type":"string","description":"Current state: \"completed\", \"running\", \"failed\"."}}},"ServiceBackupListResponse":{"type":"object","description":"Paginated list of backups for a specific external service.\n\nReturned by `GET /backups/external-services/{service_id}/backups`.","required":["backups","total","page","page_size"],"properties":{"backups":{"type":"array","items":{"$ref":"#/components/schemas/ServiceBackupEntryResponse"},"description":"Backups belonging to this service, newest first."},"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page."},"total":{"type":"integer","format":"int64","description":"Total number of backups for this service across all pages."}}},"ServiceCreateAlertRuleRequest":{"type":"object","description":"Request body for creating an alert rule on an external service.\n\nDomain-prefixed schema name — see [`AlertRuleResponse`] for why.","required":["name","metric_name","threshold","comparator","severity"],"properties":{"comparator":{"type":"string","description":"One of `>`, `<`, `>=`, `<=`."},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32","description":"Seconds the breach must persist before the alarm fires (0 = immediate)."},"metric_name":{"type":"string"},"name":{"type":"string"},"severity":{"type":"string","description":"`\"warning\"` or `\"critical\"`."},"threshold":{"type":"number","format":"double"}}},"ServiceHealthResponse":{"type":"object","required":["service_id","consecutive_failures","recent_checks"],"properties":{"consecutive_failures":{"type":"integer","format":"int32","description":"Consecutive failed probes. Alert fires at 3."},"last_checked_at":{"type":["string","null"]},"last_error":{"type":["string","null"]},"recent_checks":{"type":"array","items":{"$ref":"#/components/schemas/HealthCheckEntryResponse"},"description":"Most recent checks, newest-first (capped at `limit`)."},"response_time_ms":{"type":["integer","null"],"format":"int32"},"service_id":{"type":"integer","format":"int32"},"status":{"type":["string","null"],"description":"Current health. `null` if the service has not been probed yet.","example":"operational"},"uptime_24h_percent":{"type":["number","null"],"format":"double","description":"Uptime percentage over the last 24 hours (0.0 — 100.0).\n`null` when there is not enough history."}}},"ServiceHealthStatusBatchResponse":{"type":"object","required":["statuses"],"properties":{"statuses":{"type":"array","items":{"$ref":"#/components/schemas/ServiceHealthStatusEntryResponse"}}}},"ServiceHealthStatusEntryResponse":{"type":"object","required":["service_id","consecutive_failures"],"properties":{"consecutive_failures":{"type":"integer","format":"int32"},"last_checked_at":{"type":["string","null"]},"service_id":{"type":"integer","format":"int32"},"status":{"type":["string","null"],"description":"\"operational\" | \"degraded\" | \"down\". `null` when the service has not\nbeen probed yet.","example":"operational"}}},"ServiceMemberInfo":{"type":"object","description":"Public info about a cluster member.","required":["id","role","container_name","status","ordinal"],"properties":{"compute_ip":{"type":["string","null"],"description":"Container's IP on the `temps-overlay` multi-host network. Populated\nby the lifecycle hook (ADR-011 Phase 3); `None` on single-host\nclusters where the overlay isn't attached."},"container_name":{"type":"string"},"hostname":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"live_state":{"type":["string","null"],"description":"Live FSM state from the pg_auto_failover monitor (`primary`,\n`secondary`, `catchingup`, `report_lsn`, …). `None` when the\nmonitor is unreachable, the service is not a cluster, or the row\nis the monitor itself.\n\n**The UI must render the role badge from this field**, falling\nback to `role` only when `live_state` is null. `role` is now\nconfig-only (`monitor` or `replica`); flipping the badge to\n\"primary\" when the monitor elects a new one used to require a\nreconciler that lagged ~5s behind real failovers — and during\nthat window the UI showed two primaries. `live_state` is read\ndirectly from the monitor on every list, so it can never lag."},"node_id":{"type":["integer","null"],"format":"int32"},"ordinal":{"type":"integer","format":"int32"},"port":{"type":["integer","null"],"format":"int32"},"provisioning_error":{"type":["string","null"],"description":"Most recent provisioning failure message, when `status='failed'`.\nSet by the background task so the UI can show *why* the new\nreplica didn't come up."},"provisioning_step":{"type":["string","null"],"description":"Last-attempted phase of the async `add_cluster_member` background\ntask (e.g. `validating`, `provisioning_container`, `done`,\n`failed`). `None` for members not created through that flow —\nthe UI falls back to the `status` column for those."},"role":{"type":"string"},"status":{"type":"string"}}},"ServiceParameter":{"type":"object","required":["name","required","encrypted","description"],"properties":{"choices":{"type":["array","null"],"items":{"type":"string"}},"default_value":{"type":["string","null"]},"description":{"type":"string"},"encrypted":{"type":"boolean"},"name":{"type":"string"},"required":{"type":"boolean"},"validation_pattern":{"type":["string","null"]}}},"ServicePlan":{"type":"object","description":"Plan for migrating a single service (database, cache, etc.)","required":["name","service_type","action","action_description"],"properties":{"action":{"$ref":"#/components/schemas/ServiceAction","description":"What to do with this service"},"action_description":{"type":"string","description":"Human-readable explanation of what this action means"},"data_implications":{"type":"array","items":{"$ref":"#/components/schemas/DataImplication"},"description":"Data implications specific to this service"},"env_var_mappings":{"type":"object","description":"Environment variable key mappings: source_key -> temps_key\n\nFor example, Vercel's `POSTGRES_URL` might map to Temps' `DATABASE_URL`.\nBoth keys will be set during migration so the app works with either.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Human-readable service name"},"parameters":{"type":"object","description":"Parameters for creating the service in Temps","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"type":"string","description":"Service type (maps to temps-providers ServiceType)"},"version":{"type":["string","null"],"description":"Service version to create (e.g., \"16\" for Postgres 16)"}}},"ServiceResourceLimits":{"type":"object","description":"Optional cgroup resource limits applied to a service container.\n\nAll fields are `Option`: `None` means \"no limit\" (the kernel default),\nmatching Docker's behavior when the corresponding `HostConfig` field is\nleft at zero. Operators opt in to limits explicitly through the\n`PATCH /external-services/{id}/resources` endpoint or by writing the\n`resources` block into `ServiceConfig::parameters` at create time.\n\nThese map directly onto bollard fields:\n- `memory_mb` → `HostConfig.memory` (bytes)\n- `memory_swap_mb`→ `HostConfig.memory_swap` (bytes; ≥ memory)\n- `nano_cpus` → `HostConfig.nano_cpus` (1e9 = 1 full CPU)\n- `cpu_shares` → `HostConfig.cpu_shares` (relative weight, default 1024)\n- `shm_size_mb` → `HostConfig.shm_size` (bytes; default 64 MiB)\n\nIMPORTANT: enabling hard memory limits causes the kernel OOM killer to\nterminate the container when the working set exceeds the limit. The\ncontainer will restart (RestartPolicy::ALWAYS) but in-flight queries\nfail. Surface this clearly in any UI that lets users set limits.","properties":{"cpu_shares":{"type":["integer","null"],"format":"int64","description":"Relative CPU weight (default 1024). Only used when `nano_cpus` is None."},"memory_mb":{"type":["integer","null"],"format":"int64","description":"Hard memory limit in MiB. None = unlimited."},"memory_swap_mb":{"type":["integer","null"],"format":"int64","description":"Memory + swap limit in MiB. None = unlimited.\nMUST be >= memory_mb when both are set; Docker rejects the request otherwise.\nSet equal to `memory_mb` to disable swap entirely."},"nano_cpus":{"type":["integer","null"],"format":"int64","description":"CPU quota in nano-cpus. 1_000_000_000 = 1 full CPU core. None = unlimited."},"shm_size_mb":{"type":["integer","null"],"format":"int64","description":"Shared memory (/dev/shm) size in MiB. None = Docker default (64 MiB).\nMaps to HostConfig.shm_size (bytes). PostgreSQL uses /dev/shm for parallel\nquery workers and large work_mem; the 64 MiB default causes \"could not\nresize shared memory segment ... No space left on device\" under load.\nNOTE: shm_size is fixed at container-create time — Docker's live update\nAPI cannot change it, so changing this value recreates the container."}}},"ServiceRuntimeReport":{"type":"object","description":"Aggregate runtime info for an external service. For standalone services,\n`members` has exactly one entry. For clusters, one entry per member.","required":["service_id","topology","members"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ContainerRuntimeInfo"}},"service_id":{"type":"integer","format":"int32"},"topology":{"type":"string"}}},"ServiceStatsReport":{"type":"object","required":["service_id","topology","members"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ContainerStatsSample"}},"service_id":{"type":"integer","format":"int32"},"topology":{"type":"string"}}},"ServiceTypeInfo":{"type":"object","required":["service_type","parameters"],"properties":{"parameters":{"type":"array","items":{"$ref":"#/components/schemas/ServiceParameter"},"example":"[{\"name\": \"host\", \"required\": true, \"encrypted\": false, \"description\": \"Database host\"}]"},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"}}},"ServiceTypeRoute":{"type":"string","enum":["mariadb","mongodb","postgres","redis","s3","kv","blob","rustfs","minio"]},"ServiceUpdateAlertRuleRequest":{"type":"object","description":"Request body for updating an existing alert rule.\n\nDomain-prefixed schema name — see [`AlertRuleResponse`] for why.","properties":{"comparator":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"for_duration_secs":{"type":["integer","null"],"format":"int32"},"metric_name":{"type":["string","null"]},"name":{"type":["string","null"]},"severity":{"type":["string","null"]},"threshold":{"type":["number","null"],"format":"double"}}},"SesCredentialsRequest":{"type":"object","required":["access_key_id","secret_access_key"],"properties":{"access_key_id":{"type":"string","example":"AKIAIOSFODNN7EXAMPLE"},"secret_access_key":{"type":"string","example":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"}}},"SessionDetails":{"type":"object","required":["session_id","visitor_id","started_at","duration_seconds","is_bounced","is_engaged","page_views"],"properties":{"duration_seconds":{"type":"integer","format":"int64"},"ended_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00"},"entry_path":{"type":["string","null"]},"exit_path":{"type":["string","null"]},"is_bounced":{"type":"boolean"},"is_engaged":{"type":"boolean"},"page_views":{"type":"integer","format":"int64"},"referrer":{"type":["string","null"]},"session_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"visitor_id":{"type":"string"}}},"SessionDetailsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"SessionEvent":{"type":"object","required":["id","timestamp"],"properties":{"event_data":{},"event_name":{"type":["string","null"]},"event_type":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"page_title":{"type":["string","null"]},"page_url":{"type":["string","null"]},"timestamp":{"type":"string"}}},"SessionEventDto":{"type":"object","required":["id","session_id","data","timestamp"],"properties":{"data":{},"event_type":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"timestamp":{"type":"integer","format":"int64"}}},"SessionEventsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"SessionEventsResponse":{"type":"object","required":["session_id","events","total_count","offset","limit"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEvent"}},"limit":{"type":"integer","format":"int32"},"offset":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"total_count":{"type":"integer","format":"int64"}}},"SessionLogsQuery":{"type":"object","required":["project_id"],"properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"offset":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"sort_order":{"type":["string","null"]},"start_date":{"type":["string","null"],"format":"date-time"},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"SessionLogsResponse":{"type":"object","required":["session_id","logs","total_count","offset","limit"],"properties":{"limit":{"type":"integer","format":"int32"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/SessionRequestLog"}},"offset":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"total_count":{"type":"integer","format":"int64"}}},"SessionReplayEventsRequest":{"type":"object","required":["sessionId","events"],"properties":{"events":{"type":"string"},"sessionId":{"type":"string"}}},"SessionReplayInfoDto":{"type":"object","required":["id","visitor_id"],"properties":{"created_at":{"type":["string","null"]},"duration":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"language":{"type":["string","null"]},"screen_height":{"type":["integer","null"],"format":"int32"},"screen_width":{"type":["integer","null"],"format":"int32"},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"viewport_height":{"type":["integer","null"],"format":"int32"},"viewport_width":{"type":["integer","null"],"format":"int32"},"visitor_id":{"type":"integer","format":"int32"}}},"SessionReplayInitRequest":{"type":"object","required":["sessionId"],"properties":{"colorDepth":{"type":["integer","null"],"format":"int32","minimum":0},"language":{"type":["string","null"]},"screenHeight":{"type":["integer","null"],"format":"int32","minimum":0},"screenWidth":{"type":["integer","null"],"format":"int32","minimum":0},"sessionId":{"type":"string"},"timestamp":{"type":["string","null"]},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"userAgent":{"type":["string","null"]},"viewportHeight":{"type":["integer","null"],"format":"int32","minimum":0},"viewportWidth":{"type":["integer","null"],"format":"int32","minimum":0}}},"SessionReplayInitResponse":{"type":"object","required":["session_id","message"],"properties":{"message":{"type":"string"},"session_id":{"type":"string"}}},"SessionReplayWithEventsDto":{"type":"object","required":["session","events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEventDto"}},"session":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}}},"SessionReplayWithVisitorDto":{"type":"object","required":["id","session_replay_id","visitor_id","visitor_uuid","visitor_project_id","visitor_environment_id","visitor_first_seen","visitor_last_seen","visitor_is_crawler"],"properties":{"browser":{"type":["string","null"]},"browser_version":{"type":["string","null"]},"created_at":{"type":["string","null"]},"device_type":{"type":["string","null"]},"duration":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"language":{"type":["string","null"]},"operating_system":{"type":["string","null"]},"operating_system_version":{"type":["string","null"]},"screen_height":{"type":["integer","null"],"format":"int32"},"screen_width":{"type":["integer","null"],"format":"int32"},"session_replay_id":{"type":"string"},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"viewport_height":{"type":["integer","null"],"format":"int32"},"viewport_width":{"type":["integer","null"],"format":"int32"},"visitor_city":{"type":["string","null"]},"visitor_country":{"type":["string","null"]},"visitor_country_code":{"type":["string","null"]},"visitor_crawler_name":{"type":["string","null"]},"visitor_custom_data":{},"visitor_environment_id":{"type":"integer","format":"int32"},"visitor_first_seen":{"type":"string"},"visitor_id":{"type":"integer","format":"int32"},"visitor_is_crawler":{"type":"boolean"},"visitor_last_seen":{"type":"string"},"visitor_project_id":{"type":"integer","format":"int32"},"visitor_region":{"type":["string","null"]},"visitor_uuid":{"type":"string"}}},"SessionRequestLog":{"type":"object","required":["id","method","path","status_code","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"referrer":{"type":["string","null"]},"request_headers":{"type":["string","null"]},"response_headers":{"type":["string","null"]},"response_time_ms":{"type":["integer","null"],"format":"int32"},"status_code":{"type":"integer","format":"int32"},"user_agent":{"type":["string","null"]}}},"SessionSummary":{"type":"object","required":["session_id","started_at","duration_seconds","page_views","events_count","requests_count","is_bounced","is_engaged"],"properties":{"duration_seconds":{"type":"integer","format":"int64"},"ended_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00"},"entry_path":{"type":["string","null"]},"events_count":{"type":"integer","format":"int64"},"exit_path":{"type":["string","null"]},"is_bounced":{"type":"boolean"},"is_engaged":{"type":"boolean"},"page_views":{"type":"integer","format":"int64"},"referrer":{"type":["string","null"]},"requests_count":{"type":"integer","format":"int64"},"session_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"}}},"SetPreviewPasswordBody":{"type":"object","required":["password"],"properties":{"password":{"type":"string","description":"Plaintext password to protect the sandbox's preview URLs. Hashed\nserver-side with argon2id — we never persist or echo this back.\nMust be between 8 and 256 characters."}}},"SetPreviewPasswordResponse":{"type":"object","required":["preview_password_hint"],"properties":{"preview_password_hint":{"type":"string","description":"Last 4 chars of the password we just stored. Surface in the UI so\nusers can confirm which password is live without re-entering it."}}},"SetRequest":{"type":"object","description":"Request to set a value","required":["key","value"],"properties":{"ex":{"type":["integer","null"],"format":"int64","description":"Expire in seconds","example":3600},"key":{"type":"string","description":"The key to set","example":"user:123"},"nx":{"type":"boolean","description":"Only set if key does not exist"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"px":{"type":["integer","null"],"format":"int64","description":"Expire in milliseconds"},"value":{"description":"The value to store (can be any JSON value)"},"xx":{"type":"boolean","description":"Only set if key exists"}}},"SetResponse":{"type":"object","description":"Response for set operation","required":["result"],"properties":{"result":{"type":"string","description":"Always \"OK\" on success","example":"OK"}}},"SettingsUpdateResponse":{"type":"object","description":"Response for successful settings update","required":["message"],"properties":{"message":{"type":"string"}}},"SetupDnsChallengeRequest":{"type":"object","description":"Request to setup DNS challenge records using a configured DNS provider","required":["dns_provider_id"],"properties":{"dns_provider_id":{"type":"integer","format":"int32","description":"The ID of the DNS provider to use for creating the TXT records"}}},"SetupDnsChallengeResponse":{"type":"object","description":"Response from DNS challenge setup operation","required":["success","records_created","total_records","results","message"],"properties":{"message":{"type":"string","description":"Human-readable summary message"},"records_created":{"type":"integer","format":"int32","description":"Number of TXT records that were successfully created","minimum":0},"results":{"type":"array","items":{"$ref":"#/components/schemas/DnsChallengeRecordResult"},"description":"Results for each individual TXT record"},"success":{"type":"boolean","description":"Overall success status (true if all records were created)"},"total_records":{"type":"integer","format":"int32","description":"Total number of TXT records required for the challenge","minimum":0}}},"SetupDnsRequest":{"type":"object","description":"Request to setup DNS records using a configured DNS provider","required":["dns_provider_id"],"properties":{"dns_provider_id":{"type":"integer","format":"int32","description":"The ID of the DNS provider to use for creating records"}}},"SetupDnsResponse":{"type":"object","description":"Response from DNS setup operation","required":["success","records_created","total_records","results","message"],"properties":{"message":{"type":"string","description":"Human-readable summary message"},"records_created":{"type":"integer","format":"int32","description":"Number of records that were successfully created","minimum":0},"results":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordSetupResult"},"description":"Results for each individual record"},"success":{"type":"boolean","description":"Overall success status"},"total_records":{"type":"integer","format":"int32","description":"Total number of records attempted","minimum":0}}},"SiblingRef":{"type":"object","description":"A sibling project that shares the same `trace_id` and has opted in to\ncross-project trace sharing (`cross_project_trace_sharing = TRUE`).\n\nReturned by `CrossProjectTraceService::find_sibling_projects` and exposed\nby the Phase 1 `GET /otel/traces/cross-project/{trace_id}` endpoint.","required":["project_id","project_name","project_slug","first_seen"],"properties":{"first_seen":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the sibling project's single-project trace view."}}},"SkillDefinitionResponse":{"type":"object","required":["id","slug","name","content","has_archive","created_at","updated_at"],"properties":{"content":{"type":"string"},"created_at":{"type":"string"},"description":{"type":["string","null"]},"has_archive":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"SlackConfig":{"type":"object","required":["webhook_url"],"properties":{"channel":{"type":["string","null"]},"webhook_url":{"type":"string"}}},"SlowQueriesResponse":{"type":"object","description":"Response envelope for the slow-queries list endpoint.","required":["queries","page","page_size","total_count"],"properties":{"page":{"type":"integer","format":"int32","description":"Current page number (1-based).","minimum":0},"page_size":{"type":"integer","format":"int32","description":"Number of rows per page used for this request.","minimum":0},"queries":{"type":"array","items":{"$ref":"#/components/schemas/SlowQueryRow"},"description":"Ordered list of query stats, slowest first by mean_exec_time_ms."},"total_count":{"type":"integer","format":"int64","description":"Total number of qualifying rows across all pages.","minimum":0}}},"SlowQueryRow":{"type":"object","description":"A single entry from `pg_stat_statements`, representing one normalized\nquery fingerprint and its aggregate execution stats.","required":["query","database","calls","total_exec_time_ms","mean_exec_time_ms","rows"],"properties":{"cache_hit_ratio":{"type":["number","null"],"format":"double","description":"Shared block cache hit ratio (0.0–1.0).\n`None` when total block accesses are zero (e.g. function-only queries)."},"calls":{"type":"integer","format":"int64","description":"Number of times this query was executed."},"database":{"type":"string","description":"Name of the database this query ran against. `(dropped database)`\nwhen the originating database no longer exists but\n`pg_stat_statements` still holds stats for it."},"mean_exec_time_ms":{"type":"number","format":"double","description":"Average wall-clock time per execution, in milliseconds."},"query":{"type":"string","description":"Normalized query text (parameter literals replaced with `$N`)."},"rows":{"type":"integer","format":"int64","description":"Total number of rows returned or affected."},"total_exec_time_ms":{"type":"number","format":"double","description":"Total wall-clock time spent executing this query, in milliseconds."}}},"SmartFilter":{"oneOf":[{"type":"object","description":"Match specific page path","required":["value","type"],"properties":{"type":{"type":"string","enum":["page_path"]},"value":{"type":"string","description":"Match specific page path"}}},{"type":"object","description":"Match specific hostname","required":["value","type"],"properties":{"type":{"type":"string","enum":["hostname"]},"value":{"type":"string","description":"Match specific hostname"}}},{"type":"object","description":"Match UTM source","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_source"]},"value":{"type":"string","description":"Match UTM source"}}},{"type":"object","description":"Match UTM campaign","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_campaign"]},"value":{"type":"string","description":"Match UTM campaign"}}},{"type":"object","description":"Match UTM medium","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_medium"]},"value":{"type":"string","description":"Match UTM medium"}}},{"type":"object","description":"Match referrer hostname","required":["value","type"],"properties":{"type":{"type":"string","enum":["referrer_hostname"]},"value":{"type":"string","description":"Match referrer hostname"}}},{"type":"object","description":"Match specific channel (organic, paid, direct, referral, etc.)","required":["value","type"],"properties":{"type":{"type":"string","enum":["channel"]},"value":{"type":"string","description":"Match specific channel (organic, paid, direct, referral, etc.)"}}},{"type":"object","description":"Match device type (mobile, desktop, tablet)","required":["value","type"],"properties":{"type":{"type":"string","enum":["device_type"]},"value":{"type":"string","description":"Match device type (mobile, desktop, tablet)"}}},{"type":"object","description":"Match browser","required":["value","type"],"properties":{"type":{"type":"string","enum":["browser"]},"value":{"type":"string","description":"Match browser"}}},{"type":"object","description":"Match operating system","required":["value","type"],"properties":{"type":{"type":"string","enum":["operating_system"]},"value":{"type":"string","description":"Match operating system"}}},{"type":"object","description":"Match language","required":["value","type"],"properties":{"type":{"type":"string","enum":["language"]},"value":{"type":"string","description":"Match language"}}},{"type":"object","description":"Match custom event_data by JSON path\nFormat: {\"path\": \"user.plan\", \"value\": \"premium\"}\nThis will match events where event_data->'user'->>'plan' = 'premium'","required":["value","type"],"properties":{"type":{"type":"string","enum":["custom_data"]},"value":{"type":"object","description":"Match custom event_data by JSON path\nFormat: {\"path\": \"user.plan\", \"value\": \"premium\"}\nThis will match events where event_data->'user'->>'plan' = 'premium'","required":["path","value"],"properties":{"path":{"type":"string"},"value":{"type":"string"}}}}}],"description":"Smart filter presets for common funnel patterns"},"SmokeTestResponse":{"type":"object","required":["passed","environment","cli_installed","cli_authenticated"],"properties":{"auth_info":{"type":["string","null"],"description":"Auth email / method"},"cli_authenticated":{"type":"boolean","description":"Claude CLI authenticated?"},"cli_installed":{"type":"boolean","description":"Claude CLI installed?"},"cli_version":{"type":["string","null"],"description":"Claude CLI version"},"detail":{"type":["string","null"],"description":"Full output for debugging"},"environment":{"type":"string","description":"Where the test ran: \"host\" or \"sandbox\""},"passed":{"type":"boolean","description":"Whether the smoke test passed"},"setup_hint":{"type":["string","null"],"description":"What the user needs to do if the test failed"}}},"SmtpCredentialsRequest":{"type":"object","description":"Generic SMTP credentials request body.\n\nWorks with any SMTP relay — AWS SES SMTP endpoints, Sendgrid, Mailgun,\nPostmark, or a self-hosted Postfix. Use this when you only have SMTP\ncredentials (i.e. you cannot create identities via the upstream API).","required":["host","port"],"properties":{"accept_invalid_certs":{"type":"boolean","description":"Accept self-signed certificates. Only safe for local testing."},"encryption":{"$ref":"#/components/schemas/SmtpEncryptionRoute","description":"TLS mode. Defaults to STARTTLS."},"host":{"type":"string","description":"SMTP host, e.g. `email-smtp.eu-west-1.amazonaws.com`.","example":"email-smtp.eu-west-1.amazonaws.com"},"password":{"type":["string","null"],"description":"SMTP password / API token. Required when `username` is set."},"port":{"type":"integer","format":"int32","description":"SMTP port (587 for STARTTLS, 465 for implicit TLS, 25/1025 for plain).","example":587,"minimum":0},"username":{"type":["string","null"],"description":"SMTP username. Leave empty for unauthenticated relays.","example":"AKIAIOSFODNN7EXAMPLE"}}},"SmtpEncryptionRoute":{"type":"string","description":"TLS mode for the SMTP relay.","enum":["starttls","tls","none"]},"SmtpResult":{"type":"object","description":"SMTP validation result","required":["can_connect_smtp","has_full_inbox","is_catch_all","is_deliverable","is_disabled"],"properties":{"can_connect_smtp":{"type":"boolean","description":"Whether we could connect to the SMTP server"},"error":{"type":["string","null"],"description":"Error message if SMTP check failed"},"has_full_inbox":{"type":"boolean","description":"Whether the mailbox appears to have a full inbox"},"is_catch_all":{"type":"boolean","description":"Whether this is a catch-all domain"},"is_deliverable":{"type":"boolean","description":"Whether the email is deliverable"},"is_disabled":{"type":"boolean","description":"Whether the mailbox is disabled"}}},"SourceBackupEntry":{"type":"object","description":"Entry in the source backup index. Covers both DB-tracked backups\n(have a row in `backups`) and S3-scan discoveries (raw S3 objects with\nno DB row — used for disaster-recovery from another Temps instance).","required":["id","backup_id","name","backup_type","created_at","location","metadata_location","source","state"],"properties":{"backup_id":{"type":"string","description":"UUID identifier from the DB row. Empty for S3-scan entries.","example":"550e8400-e29b-41d4-a716-446655440000"},"backup_type":{"type":"string","description":"Backup variant as recorded by the backup pipeline (e.g. \"full\").","example":"full"},"created_at":{"type":"string","description":"When the backup was created. For S3-scan entries this is the\nobject's LastModified time.","example":"2024-01-15T14:30:00.123Z"},"engine":{"type":["string","null"],"description":"Engine that produced the backup (\"postgres\", \"redis\", \"mongodb\",\n\"s3\", \"rustfs\"). Used by the UI to mark engine-compat with the\ntarget service.","example":"postgres"},"format":{"type":["string","null"],"description":"Storage format: \"walg\" for continuous-archive (PITR-capable),\n\"pg_dump\" for point-in-time dumps, \"\" for non-postgres.","example":"walg"},"id":{"type":"integer","format":"int32","description":"DB row id. Zero for S3-scan entries that have no DB row.","example":1},"location":{"type":"string","description":"Raw S3 URL / key where the backup sits. For Postgres WAL-G backups\nthis starts with `s3://`; for pg_dump-style backups it's the\nrelative object key.","example":"s3://bucket/external_services/postgres/svc-name/walg"},"metadata_location":{"type":"string","description":"Sidecar metadata.json location, if any. Empty when none.","example":""},"name":{"type":"string","description":"Human-friendly display name (\"postgres backup (svc-name)\" for DB\nrows, or a synthesized label derived from the S3 path for scans).","example":"postgres backup (postgres-n4ea)"},"origin_service_name":{"type":["string","null"],"description":"Name of the service that produced the backup. For S3-scan entries\nthis is parsed from the S3 path.","example":"postgres-n4ea"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the backup in bytes, if known.","example":1024000},"source":{"type":"string","description":"Provenance: \"db\" for rows in this Temps, \"s3_scan\" for objects\ndiscovered by the S3 bucket walk (e.g., backups made by another\nTemps instance).","example":"db"},"state":{"type":"string","description":"Observed state (\"completed\", \"running\", \"failed\") — DB only.\nEmpty string for S3-scan entries.","example":"completed"}}},"SourceBackupIndexResponse":{"type":"object","description":"Response type for source backup index","required":["backups","last_updated"],"properties":{"backups":{"type":"array","items":{"$ref":"#/components/schemas/SourceBackupEntry"},"description":"List of backups in the source"},"last_updated":{"type":"string","description":"When the index was last updated","example":"2024-01-15T14:30:00.123Z"}}},"SourceBody":{"oneOf":[{"type":"object","required":["url","type"],"properties":{"depth":{"type":["integer","null"],"format":"int32","minimum":0},"git_connection_id":{"type":["integer","null"],"format":"int32"},"password":{"type":["string","null"]},"revision":{"type":["string","null"]},"type":{"type":"string","enum":["git"]},"url":{"type":"string"},"username":{"type":["string","null"]}}},{"type":"object","required":["url","type"],"properties":{"type":{"type":"string","enum":["tarball"]},"url":{"type":"string"}}}],"description":"Initial content to seed into the sandbox work dir. Mirrors the\n`@vercel/sandbox` `source` option. `type` is one of:\n- `git` — clone `url`; optionally check out `revision`\n- `tarball` — download `url` (must be tar or tar.gz) and extract\n\nFor private git repos, pass credentials one of two ways:\n1. **Inline (SDK-compatible):** `username` + `password`. GitHub\n tokens use `username: \"x-access-token\"`.\n2. **Stored connection (temps-native):** `git_connection_id`\n references a row in the caller's git provider connections. Temps\n resolves the token server-side and injects it safely.\n\n`git_connection_id` is mutually exclusive with `username`/`password`."},"SourceFileListResponse":{"type":"object","required":["source_files","total"],"properties":{"source_files":{"type":"array","items":{"$ref":"#/components/schemas/SourceFileResponse"}},"total":{"type":"integer","minimum":0}}},"SourceFileResponse":{"type":"object","required":["id","project_id","release","file_path","size_bytes","created_at"],"properties":{"checksum":{"type":["string","null"]},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"file_path":{"type":"string"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"release":{"type":"string"},"size_bytes":{"type":"integer","format":"int64"}}},"SourceMapListResponse":{"type":"object","required":["source_maps","total"],"properties":{"source_maps":{"type":"array","items":{"$ref":"#/components/schemas/SourceMapResponse"}},"total":{"type":"integer","minimum":0}}},"SourceMapResponse":{"type":"object","required":["id","project_id","release","file_path","size_bytes","created_at"],"properties":{"checksum":{"type":["string","null"]},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"dist":{"type":["string","null"]},"file_path":{"type":"string"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"release":{"type":"string"},"size_bytes":{"type":"integer","format":"int64"}}},"SourceType":{"type":"string","description":"Source type for project deployments\n\nDetermines where the deployment artifacts come from:\n- `Git`: Source code from a Git repository (traditional flow)\n- `DockerImage`: Pre-built Docker image from external registry\n- `StaticFiles`: Pre-built static files uploaded as a bundle\n- `Manual`: Flexible type that accepts any deployment method","enum":["git","docker_image","static_files","manual"]},"SpanEvent":{"type":"object","description":"A span event (log-like annotation on a span).","required":["timestamp","name","attributes"],"properties":{"attributes":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"SpanKind":{"type":"string","description":"Span kind.","enum":["UNSPECIFIED","INTERNAL","SERVER","CLIENT","PRODUCER","CONSUMER"]},"SpanRecord":{"type":"object","description":"A single trace span ready for storage.","required":["project_id","resource","trace_id","span_id","name","kind","start_time","end_time","duration_ms","status_code","status_message","attributes","events"],"properties":{"attributes":{"type":"object","description":"Raw key/value pairs exactly as reported by the instrumenting library.\nNumeric values are NOT guaranteed to share `duration_ms`'s unit — they\nmay be seconds, milliseconds, microseconds, or nanoseconds depending on\nthe exporter's own convention, and the unit is not labeled here.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"deployment_id":{"type":["integer","null"],"format":"int32"},"duration_ms":{"type":"number","format":"double","description":"Span duration in milliseconds. The only field on this struct guaranteed\nto be in milliseconds."},"end_time":{"type":"string","format":"date-time"},"events":{"type":"array","items":{"$ref":"#/components/schemas/SpanEvent"}},"kind":{"$ref":"#/components/schemas/SpanKind"},"name":{"type":"string"},"parent_span_id":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"resource":{"$ref":"#/components/schemas/ResourceInfo"},"span_id":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"status_message":{"type":"string"},"trace_id":{"type":"string"}}},"SpanRow":{"type":"object","required":["id","ts","trace_id","span_id","service","operation","attributes","attributes_truncated"],"properties":{"attributes":{},"attributes_truncated":{"type":"boolean"},"deployment_id":{"type":["integer","null"],"format":"int32"},"duration_ms":{"type":["number","null"],"format":"double"},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"operation":{"type":"string"},"parent_span_id":{"type":["string","null"]},"service":{"type":"string"},"span_id":{"type":"string"},"status":{"type":["string","null"]},"trace_id":{"type":"string"},"ts":{"type":"string","format":"date-time"}}},"SpanStatusCode":{"type":"string","description":"Span status code.","enum":["UNSET","OK","ERROR"]},"SpeedMetricsPayload":{"type":"object","description":"Speed metrics payload for recording web vitals","properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"fcp":{"type":["number","null"],"format":"float","description":"First Contentful Paint (milliseconds)"},"fid":{"type":["number","null"],"format":"float","description":"First Input Delay (milliseconds)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"},"language":{"type":["string","null"],"description":"Browser language"},"lcp":{"type":["number","null"],"format":"float","description":"Largest Contentful Paint (milliseconds)"},"pathname":{"type":["string","null"],"description":"Page pathname"},"query":{"type":["string","null"],"description":"Query string"},"screenHeight":{"type":["integer","null"],"format":"int32","description":"Screen height in pixels"},"screenWidth":{"type":["integer","null"],"format":"int32","description":"Screen width in pixels"},"ttfb":{"type":["number","null"],"format":"float","description":"Time to First Byte (milliseconds)"},"viewportHeight":{"type":["integer","null"],"format":"int32","description":"Viewport height in pixels"},"viewportWidth":{"type":["integer","null"],"format":"int32","description":"Viewport width in pixels"}}},"SpeedSegmentFilters":{"type":"object","description":"Optional segment filters for the performance read endpoints, mirroring\nanalytics' `VisitorSegmentFilters`. Each filter narrows results to samples\nmatching the dimension value, so metrics can be scoped to e.g. one page,\none browser, or one country. Geographic filters resolve via\n`ip_geolocations`; the rest live directly on `performance_metrics`.","properties":{"filter_browser":{"type":["string","null"],"description":"Browser name (matches `performance_metrics.browser`)"},"filter_city":{"type":["string","null"],"description":"Geolocation city (matches `ip_geolocations.city`)"},"filter_country":{"type":["string","null"],"description":"Geolocation country (matches `ip_geolocations.country`)"},"filter_operating_system":{"type":["string","null"],"description":"Operating system (matches `performance_metrics.operating_system`)"},"filter_path":{"type":["string","null"],"description":"Page pathname (matches `performance_metrics.pathname`)"},"filter_region":{"type":["string","null"],"description":"Geolocation region (matches `ip_geolocations.region`)"}}},"StaleSlot":{"type":"object","required":["slot_name","active","retained_bytes"],"properties":{"active":{"type":"boolean"},"retained_bytes":{"type":"integer","format":"int64"},"slot_name":{"type":"string"}}},"StartAnalysisRequest":{"type":"object","required":["error_group_id"],"properties":{"branch":{"type":["string","null"],"description":"Branch to clone instead of the project's main branch."},"error_group_id":{"type":"integer","format":"int32"},"max_turns":{"type":["integer","null"],"format":"int32","description":"Per-run turn cap applied to every phase (1–200). Only enforced for\nCLIs with a turn flag (Claude Code). `None` uses the provider's\nconfigured defaults."},"model":{"type":["string","null"],"description":"Model id for the chosen provider. `None` uses the provider's saved\ndefault model."},"provider":{"type":["string","null"],"description":"AI provider id (\"claude_cli\", \"codex_cli\", \"opencode\"). `None` uses\nthe platform default provider."},"user_context":{"type":["string","null"],"description":"Free-text notes for the model (extra context about the error, retry\nguidance, constraints). Included verbatim in the analysis prompt."}}},"StartPgUpgradeRequest":{"type":"object","required":["from_version","to_version","from_image","to_image"],"properties":{"from_image":{"type":"string","example":"postgres:16-bookworm"},"from_version":{"type":"string","example":"16"},"to_image":{"type":"string","example":"postgres:17-bookworm"},"to_version":{"type":"string","example":"17"}}},"StartRestoreRequest":{"allOf":[{"$ref":"#/components/schemas/RestoreRequestMode","description":"Requested restore mode. See `RestoreRequestMode`."},{"type":"object","properties":{"backup_engine":{"type":["string","null"],"description":"Engine of the backup when specified by `backup_location`\n(\"postgres\", \"redis\", \"mongodb\", \"s3\"). Ignored when `backup_id`\nis used — we infer from the DB row."},"backup_id":{"type":["integer","null"],"format":"int32","description":"DB id of the backup to restore from. Either `backup_id` or\n`backup_location` MUST be provided. Use `backup_id` when restoring\na backup this Temps instance recorded."},"backup_location":{"type":["string","null"],"description":"Raw S3 URL / key of the backup — used when restoring a backup\ndiscovered by S3 scan (i.e., produced by another Temps instance).\nRequires `backup_engine` and `s3_source_id` to also be set."},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"S3 source the `backup_location` lives in. Ignored when `backup_id`\nis used."}}}]},"StatResponse":{"type":"object","required":["path","exists","is_dir","is_file","size"],"properties":{"exists":{"type":"boolean"},"is_dir":{"type":"boolean"},"is_file":{"type":"boolean"},"path":{"type":"string"},"size":{"type":"integer","format":"int64","minimum":0}}},"StaticBundleResponse":{"type":"object","required":["id","project_id","blob_path","content_type","size_bytes","uploaded_at","created_at"],"properties":{"blob_path":{"type":"string"},"checksum":{"type":["string","null"]},"content_type":{"type":"string"},"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"format":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"metadata":{},"original_filename":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"size_bytes":{"type":"integer","format":"int64"},"uploaded_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"}}},"StaticParams":{"type":"object","description":"Static threshold detector: compare the aggregated `value` against `threshold`.","required":["comparator","threshold"],"properties":{"comparator":{"$ref":"#/components/schemas/Comparator","description":"How `value` is compared against `threshold`."},"threshold":{"type":"number","format":"double","description":"The threshold the aggregated value is compared against."}}},"StaticPresetConfig":{"type":"object","description":"Configuration for static site presets (Vite, Next.js, Docusaurus, etc.)\nThese presets build static sites that are served via a web server","properties":{"buildCommand":{"type":["string","null"],"description":"Custom build command (overrides preset default)","example":"npm run build:production"},"buildContext":{"type":["string","null"],"description":"Custom build context path (relative to repository root)\nUseful for monorepo setups where the app is in a subdirectory","example":"./apps/frontend"},"installCommand":{"type":["string","null"],"description":"Custom install command (overrides auto-detected package manager)","example":"npm ci"},"outputDir":{"type":["string","null"],"description":"Custom output directory (overrides preset default)\nCommon values: \"dist\", \"build\", \".next\", \"out\"","example":"dist"}}},"StatsFilters":{"type":"object","description":"Filters for statistics queries","properties":{"client_ip":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"has_project":{"type":["boolean","null"],"description":"When true, only count requests that matched a project (project_id IS NOT NULL).\nUsed by the health dashboard so totals match the per-project cards."},"host":{"type":["string","null"]},"is_bot":{"type":["boolean","null"]},"method":{"type":["string","null"]},"project_id":{"type":["integer","null"],"format":"int32"},"request_source":{"type":["string","null"]},"routing_status":{"type":["string","null"]},"status_code":{"type":["integer","null"],"format":"int32"},"status_code_class":{"type":["string","null"],"description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")"}}},"StatusBucket":{"type":"object","required":["bucket_start","status","total_checks","operational_count","degraded_count","down_count","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["number","null"],"format":"double"},"bucket_start":{"type":"string","format":"date-time"},"degraded_count":{"type":"integer","format":"int64"},"down_count":{"type":"integer","format":"int64"},"max_response_time_ms":{"type":["number","null"],"format":"double"},"min_response_time_ms":{"type":["number","null"],"format":"double"},"operational_count":{"type":"integer","format":"int64"},"p50_response_time_ms":{"type":["number","null"],"format":"double"},"p95_response_time_ms":{"type":["number","null"],"format":"double"},"p99_response_time_ms":{"type":["number","null"],"format":"double"},"status":{"type":"string"},"total_checks":{"type":"integer","format":"int64"},"uptime_percentage":{"type":"number","format":"double"}}},"StatusBucketedResponse":{"type":"object","required":["monitor_id","interval","buckets"],"properties":{"buckets":{"type":"array","items":{"$ref":"#/components/schemas/StatusBucket"}},"interval":{"type":"string"},"monitor_id":{"type":"integer","format":"int32"}}},"StatusCodeCount":{"type":"object","required":["status_code","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"status_code":{"type":"integer","format":"int32"}}},"StatusCodesQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"StatusPageOverview":{"type":"object","required":["status","monitors","recent_incidents"],"properties":{"monitors":{"type":"array","items":{"$ref":"#/components/schemas/MonitorStatus"}},"recent_incidents":{"type":"array","items":{"$ref":"#/components/schemas/IncidentResponse"}},"status":{"type":"string"}}},"StepConversionResponse":{"type":"object","required":["step_id","step_name","step_order","completions","conversion_rate","drop_off_rate","average_time_to_complete_seconds"],"properties":{"average_time_to_complete_seconds":{"type":"number","format":"double"},"completions":{"type":"integer","format":"int64","minimum":0},"conversion_rate":{"type":"number","format":"double"},"drop_off_rate":{"type":"number","format":"double"},"step_id":{"type":"integer","format":"int32"},"step_name":{"type":"string"},"step_order":{"type":"integer","format":"int32"}}},"StepResourceType":{"type":"string","description":"What kind of resource a migration step operates on","enum":["project","environment","deployment","environment-variable","service","domain","git-link","other"]},"StepResult":{"type":"object","description":"Result of executing a single migration step","required":["step_id","step_title","success","skipped","message","created_resources","duration_seconds"],"properties":{"created_resources":{"type":"array","items":{"$ref":"#/components/schemas/CreatedResource"},"description":"Resources created by this step"},"duration_seconds":{"type":"number","format":"double","description":"Duration of this step"},"message":{"type":"string","description":"Human-readable message about what happened"},"skipped":{"type":"boolean","description":"Whether this step was skipped"},"step_id":{"type":"string","description":"Step ID (matches `MigrationStep.id`)"},"step_title":{"type":"string","description":"Step title (for display)"},"success":{"type":"boolean","description":"Whether this step succeeded"}}},"StopSequence":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"StorageQuota":{"type":"object","description":"Quota usage information for a project.","required":["project_id","metrics_bytes","traces_bytes","logs_bytes","total_bytes","limit_bytes","usage_pct"],"properties":{"limit_bytes":{"type":"integer","format":"int64","minimum":0},"logs_bytes":{"type":"integer","format":"int64","minimum":0},"metrics_bytes":{"type":"integer","format":"int64","minimum":0},"project_id":{"type":"integer","format":"int32"},"total_bytes":{"type":"integer","format":"int64","minimum":0},"traces_bytes":{"type":"integer","format":"int64","minimum":0},"usage_pct":{"type":"number","format":"double"}}},"StripeConfig":{"type":"object","properties":{"include_unpriced_charges":{"type":"boolean","description":"When an allowlist is set, should we still ingest charges that\nlack a price reference (e.g. standalone `charge.succeeded` without\na subscription)? Default true — charges don't belong to a SKU."},"metered_mode":{"$ref":"#/components/schemas/MeteredMode","description":"How to compute MRR for metered / tiered / hybrid subscriptions."},"price_allowlist":{"type":"array","items":{"type":"string"},"description":"Only events tagged with one of these Stripe price IDs are ingested.\nEmpty = accept all prices."},"product_allowlist":{"type":"array","items":{"type":"string"},"description":"Only events tagged with one of these Stripe product IDs are\ningested. Empty = accept all products. Combined with\n`price_allowlist` via OR — if either list has a match, accept."}}},"SyncedRepositoryListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"language":{"type":["string","null"]},"owner":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"private":{"type":["boolean","null"]},"search":{"type":["string","null"]},"sort":{"type":["string","null"]}}},"SyntaxResult":{"type":"object","description":"Syntax validation result","required":["is_valid_syntax"],"properties":{"domain":{"type":["string","null"],"description":"The domain part of the email","example":"gmail.com"},"is_valid_syntax":{"type":"boolean","description":"Whether the email syntax is valid"},"suggestion":{"type":["string","null"],"description":"Suggested email correction if available"},"username":{"type":["string","null"],"description":"The username part of the email","example":"someone"}}},"TagInfo":{"type":"object","required":["name","commit_sha"],"properties":{"commit_sha":{"type":"string"},"name":{"type":"string"}}},"TagListResponse":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagInfo"}}}},"TailLogsRequest":{"type":"object","required":["project_id","service","env"],"properties":{"env":{"type":"string"},"external_service_id":{"type":["integer","null"],"format":"int32","description":"When set, tail an imported/managed external service's logs instead of\na project's (`project_id` is ignored in this mode)."},"levels":{"type":"array","items":{"type":"string"}},"project_id":{"type":"integer","format":"int32","description":"Project ID (integer, as used by the rest of the platform)"},"service":{"type":"string"},"text":{"type":["string","null"]}}},"TargetRecommendation":{"type":"object","description":"The temps/Hetzner target sizing and savings estimate","required":["server_type","vcpus","memory_gb","monthly_eur","fits_single_node","sizing_basis","rationale"],"properties":{"fits_single_node":{"type":"boolean","description":"Whether the workloads fit a single recommended server. When `false`,\nthe rationale explains the multi-node option (temps worker nodes)."},"memory_gb":{"type":"integer","format":"int32","description":"Memory (GB) of the recommended server"},"monthly_eur":{"type":"number","format":"double","description":"Estimated monthly price of the recommended server in EUR"},"monthly_savings_usd":{"type":["number","null"],"format":"double","description":"Estimated monthly savings in USD (current cost minus target cost,\ntreating EUR≈USD for the rough comparison — disclaimed in `notes`).\n`None` when the current cost is unknown."},"rationale":{"type":"string","description":"Human-readable recommendation summary"},"server_type":{"type":"string","description":"Recommended Hetzner server type (e.g. \"cpx32\")"},"sizing_basis":{"type":"string","description":"What the sizing was based on, e.g. \"2× measured usage + temps\nplatform overhead\" or \"resource requests (no metrics available)\""},"vcpus":{"type":"integer","format":"int32","description":"vCPUs of the recommended server"},"yearly_savings_usd":{"type":["number","null"],"format":"double","description":"`monthly_savings_usd × 12`"}}},"TemplateResponse":{"type":"object","description":"Response type for a single template","required":["slug","name","git","preset","tags","features","services","env_vars","is_featured"],"properties":{"description":{"type":["string","null"],"description":"Short description"},"env_vars":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarTemplateResponse"},"description":"Environment variables template"},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Container port the prebuilt image listens on (image deploys only)."},"features":{"type":"array","items":{"type":"string"},"description":"Feature highlights"},"git":{"$ref":"#/components/schemas/GitRefResponse","description":"Git repository reference"},"health_check_path":{"type":["string","null"],"description":"HTTP health-check path probed after the container starts (image deploys)."},"image":{"type":["string","null"],"description":"Prebuilt Docker image reference. When set, the one-click deploy pulls and\nruns this image directly (no build); when absent it builds from `git`."},"image_url":{"type":["string","null"],"description":"URL to template image/icon"},"is_featured":{"type":"boolean","description":"Whether the template is featured/promoted"},"name":{"type":"string","description":"Display name"},"preset":{"type":"string","description":"Framework/preset to use"},"screenshot_url":{"type":["string","null"],"description":"URL to a wide screenshot/banner preview of the deployed template.\nAbsent for templates that don't have one captured yet."},"services":{"type":"array","items":{"type":"string"},"description":"Required external services"},"slug":{"type":"string","description":"Unique identifier for the template (used in URLs)"},"tags":{"type":"array","items":{"type":"string"},"description":"Tags/categories for filtering"}}},"TestEmailRequest":{"type":"object","description":"Request body for testing an email provider","required":["from"],"properties":{"from":{"type":"string","description":"Sender email address (must be verified with the provider)","example":"test@example.com"},"from_name":{"type":["string","null"],"description":"Sender display name","example":"My App"}}},"TestEmailResponse":{"type":"object","description":"Response for test email endpoint","required":["success","sent_to"],"properties":{"error":{"type":["string","null"],"description":"Error message if the test failed"},"provider_message_id":{"type":["string","null"],"description":"Provider message ID if successful"},"sent_to":{"type":"string","description":"The email address the test was sent to","example":"user@example.com"},"success":{"type":"boolean","description":"Whether the test email was sent successfully"}}},"TestProviderKeyRequest":{"type":"object","required":["provider","api_key"],"properties":{"api_key":{"type":"string","description":"The raw API key to test"},"base_url":{"type":["string","null"],"description":"Optional custom base URL"},"provider":{"type":"string","description":"Provider ID: \"openai\", \"anthropic\", \"xai\", \"gemini\""}}},"TestProviderKeyResponse":{"type":"object","required":["success","provider","latency_ms"],"properties":{"error":{"type":["string","null"],"description":"Error message if the test failed"},"latency_ms":{"type":"integer","format":"int64","description":"Response time in milliseconds","minimum":0},"provider":{"type":"string"},"success":{"type":"boolean"}}},"TestProviderResponse":{"type":"object","required":["success"],"properties":{"message":{"type":["string","null"]},"success":{"type":"boolean"}}},"TimeBucketStats":{"type":"object","description":"Time bucket statistics response","required":["bucket","request_count","avg_response_time_ms","error_count","total_request_bytes","total_response_bytes"],"properties":{"avg_response_time_ms":{"type":"number","format":"double","description":"Average response time in milliseconds"},"bucket":{"type":"string","description":"Bucket timestamp in RFC3339 format","example":"2025-10-23T12:00:00Z"},"error_count":{"type":"integer","format":"int64","description":"Number of errors (status >= 400)"},"request_count":{"type":"integer","format":"int64","description":"Total number of requests in this bucket"},"total_request_bytes":{"type":"integer","format":"int64","description":"Total request bytes"},"total_response_bytes":{"type":"integer","format":"int64","description":"Total response bytes"}}},"TimeBucketStatsResponse":{"type":"object","description":"Response for time bucket stats","required":["stats","start_time","end_time","bucket_interval"],"properties":{"bucket_interval":{"type":"string"},"end_time":{"type":"string"},"start_time":{"type":"string"},"stats":{"type":"array","items":{"$ref":"#/components/schemas/TimeBucketStats"}}}},"TimeseriesBucket":{"type":"object","required":["bucket","request_count","input_tokens","output_tokens","avg_latency_ms"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"bucket":{"type":"string","description":"ISO 8601 timestamp"},"input_tokens":{"type":"integer","format":"int64"},"output_tokens":{"type":"integer","format":"int64"},"request_count":{"type":"integer","format":"int64"}}},"TimeseriesQueryParams":{"type":"object","properties":{"bucket":{"type":["string","null"],"description":"Bucket size: \"hour\", \"day\", \"week\" (defaults to \"day\")"},"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"model":{"type":["string","null"],"description":"Filter by model name"},"provider":{"type":["string","null"],"description":"Filter by provider name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"TlsMode":{"type":"string","enum":["None","Starttls","Tls"]},"TodayStatsResponse":{"type":"object","description":"Today's stats response","required":["total_requests","date"],"properties":{"date":{"type":"string","description":"Date for which stats are returned","example":"2025-10-23"},"total_requests":{"type":"integer","format":"int64","description":"Total requests today"}}},"ToggleDeploymentMetricsRequest":{"type":"object","description":"Request body to toggle OTLP metric ingestion for a deployment.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether to enable (`true`) or disable (`false`) metric ingestion."},"path":{"type":["string","null"],"description":"Prometheus scrape path (optional, defaults to `/metrics`)."},"port":{"type":["integer","null"],"format":"int32","description":"Prometheus scrape port (optional).","minimum":0}}},"ToggleServiceMetricsRequest":{"type":"object","description":"Request body to toggle metric collection for an external service.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether to enable (`true`) or disable (`false`) metric collection."}}},"TokenRenewalRequest":{"type":"object","required":["refresh_token"],"properties":{"refresh_token":{"type":"string"}}},"ToolCallEvent":{"type":"object","description":"Payload for the `tool_call` SSE event: the model is about to run a tool.\nSerialized as compact single-line JSON onto one `data:` line.","required":["id","name","arguments"],"properties":{"arguments":{"type":"string","description":"The raw JSON-args string the model emitted."},"id":{"type":"string"},"name":{"type":"string"}}},"ToolInfo":{"type":"object","description":"One persisted tool invocation + its result, attached to an assistant message.","required":["id","name","arguments"],"properties":{"arguments":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"result":{"type":["string","null"]}}},"ToolResultEvent":{"type":"object","description":"Payload for the `tool_result` SSE event: a tool finished running. Serialized\nas compact single-line JSON; `content` is JSON-string-escaped so it stays on\none `data:` line even when long.","required":["id","name","content"],"properties":{"content":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}}},"TopModelsQueryParams":{"type":"object","properties":{"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"limit":{"type":["integer","null"],"format":"int64","description":"Max results (defaults to 10)","minimum":0},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"TraceProjectRef":{"type":"object","description":"All projects that contributed spans to a trace, including their sharing flag.\n\nReturned by `CrossProjectTraceService::find_trace_projects`.","required":["project_id","project_name","project_slug","first_seen","sharing"],"properties":{"first_seen":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the project's single-project trace view."},"sharing":{"type":"boolean","description":"Whether this project has `cross_project_trace_sharing = true`."}}},"TraceSummariesResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TraceSummary"}},"total":{"type":["integer","null"],"format":"int64","description":"Total traces matching the filters, ignoring pagination. Omitted when\nthe request passed `include_total=false`, in which case the caller\nasked not to pay for the count — treat its absence as \"unknown\", not\nas zero.","minimum":0}}},"TraceSummary":{"type":"object","description":"A trace summary for the list view — one row per trace, aggregated from spans.","required":["trace_id","root_span_name","service_name","kind","status_code","start_time","duration_ms","span_count","error_count"],"properties":{"deployment_environment":{"type":["string","null"],"description":"The deployment environment from the root span's resource attributes (e.g. \"production\")."},"duration_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"kind":{"$ref":"#/components/schemas/SpanKind"},"root_span_name":{"type":"string"},"service_name":{"type":"string"},"span_count":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"trace_id":{"type":"string"}}},"TracesResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/SpanRecord"}}}},"TrackedLinkResponse":{"type":"object","description":"Tracked link with click count","required":["link_index","original_url","click_count"],"properties":{"click_count":{"type":"integer","format":"int32"},"link_index":{"type":"integer","format":"int32"},"original_url":{"type":"string"}}},"TrackingEventResponse":{"type":"object","description":"Email tracking event","required":["id","email_id","event_type","created_at"],"properties":{"created_at":{"type":"string"},"email_id":{"type":"string"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"ip_address":{"type":["string","null"]},"link_index":{"type":["integer","null"],"format":"int32"},"link_url":{"type":["string","null"]},"user_agent":{"type":["string","null"]}}},"TriggerAgentRequest":{"type":"object","properties":{"trigger_source_id":{"type":["integer","null"],"format":"int32"},"trigger_source_type":{"type":["string","null"]},"user_context":{"type":["string","null"],"description":"Optional context from the user (e.g. a research topic, bug description, or instructions)."}}},"TriggerDigestResponse":{"type":"object","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"TriggerPipelinePayload":{"type":"object","properties":{"branch":{"type":["string","null"]},"commit":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID - if not provided, will use the project's preview environment"},"tag":{"type":["string","null"]}}},"TriggerPipelineResponse":{"type":"object","required":["message","project_id","environment_id"],"properties":{"branch":{"type":["string","null"]},"commit":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"message":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"tag":{"type":["string","null"]}}},"TriggerScanRequest":{"type":"object","required":["environment_id"],"properties":{"environment_id":{"type":"integer","format":"int32","description":"Environment ID to scan (uses the current deployment for this environment)","example":1}}},"TriggerScanResponse":{"type":"object","required":["scan_id","status","message"],"properties":{"message":{"type":"string"},"scan_id":{"type":"integer","format":"int32"},"status":{"type":"string"}}},"TtlRequest":{"type":"object","description":"Request to get TTL for a key","required":["key"],"properties":{"key":{"type":"string","description":"The key to check TTL for","example":"session:abc"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"TtlResponse":{"type":"object","description":"Response for TTL operation","required":["ttl"],"properties":{"ttl":{"type":"integer","format":"int64","description":"TTL in seconds, -1 if no expiration, -2 if key doesn't exist","example":3600}}},"TxtRecord":{"type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string"}}},"UiManifest":{"type":"object","description":"Describes the plugin's embedded UI bundle.","required":["entry_js"],"properties":{"css":{"type":"array","items":{"type":"string"},"description":"CSS files to load"},"entry_js":{"type":"string","description":"JavaScript entry point filename relative to the bundle root"},"routes":{"type":"array","items":{"$ref":"#/components/schemas/UiRoute"},"description":"Client-side routes the plugin handles"}}},"UiRoute":{"type":"object","description":"A client-side route provided by the plugin UI.","required":["path","title"],"properties":{"path":{"type":"string","description":"Route path pattern (e.g., \"/my-plugin\", \"/my-plugin/:id\")"},"title":{"type":"string","description":"Page title for breadcrumbs"}}},"UndrainNodeResponse":{"type":"object","description":"Response after undraining (reactivating) a node.","required":["id","name","status","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"UnifiedTrace":{"type":"object","description":"Merged cross-project trace result (Phase 2 unified waterfall).\n\nSpans are sorted by `start_time ASC`. At most 20 projects and 10,000\nspans total are included; `truncated` / `truncated_projects` signal when\nthe caps were hit.","required":["trace_id","projects","spans","start_time","end_time","total_duration_ms","span_count","error_count","has_redacted_spans","truncated","truncated_projects"],"properties":{"end_time":{"type":"string","format":"date-time"},"error_count":{"type":"integer","minimum":0},"has_redacted_spans":{"type":"boolean","description":"`true` when at least one project has `cross_project_trace_sharing = false`\nand its spans were therefore excluded from the result set."},"projects":{"type":"array","items":{"$ref":"#/components/schemas/ProjectRef"},"description":"Projects that contributed spans to this result set."},"span_count":{"type":"integer","minimum":0},"spans":{"type":"array","items":{"$ref":"#/components/schemas/AnnotatedSpan"},"description":"Annotated, merged span list sorted by `start_time ASC`."},"start_time":{"type":"string","format":"date-time"},"total_duration_ms":{"type":"number","format":"double","description":"Trace wall-clock duration in milliseconds (`end_time – start_time`)."},"trace_id":{"type":"string"},"truncated":{"type":"boolean","description":"`true` when the 20-project or 10,000-span cap was hit."},"truncated_projects":{"type":"array","items":{"type":"integer","format":"int32"},"description":"project_ids excluded due to truncation (most-recent first_seen dropped first)."}}},"UniqueCountsQuery":{"type":"object","description":"Query parameters for unique counts over time frame","required":["start_date","end_date"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"metric":{"type":"string","description":"Metric to count: \"sessions\" (unique sessions), \"visitors\" (unique visitors),\n\"returning_visitors\" (visitors seen before the range), or \"page_views\"\n(total page views) (default: \"sessions\")"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"UniqueCountsResponse":{"type":"object","required":["count"],"properties":{"count":{"type":"integer","format":"int64"}}},"UnsupportedFeature":{"type":"object","description":"A feature from the source platform that cannot be migrated","required":["feature","reason"],"properties":{"alternative":{"type":["string","null"],"description":"Suggested alternative in Temps (if any)"},"feature":{"type":"string","description":"Feature name (e.g., \"Edge Middleware\", \"Serverless Functions\", \"Cron Jobs\")"},"reason":{"type":"string","description":"Why it can't be migrated"}}},"UpdateAdminGateRequest":{"type":"object","required":["allowed_ips","allowed_hosts","trust_forwarded_for"],"properties":{"allowed_hosts":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"}},"trust_forwarded_for":{"type":"boolean"}}},"UpdateAiProviderRequest":{"type":"object","description":"Body for `PATCH /settings/ai-providers/{provider_id}` — updates\nprovider-scoped settings (just the default model for now) without\ntouching the credential. Keeping credentials out of this shape means\nthe UI can auto-save model changes on select, without forcing the user\nto re-paste their token or config file.\nName-spaced schema name avoids an OpenAPI collision with\n`temps-notifications::UpdateProviderRequest`, which has different fields.\nBoth are exposed as `utoipa::ToSchema`; without the override the merged\nOpenAPI doc would silently shadow one struct with the other and break\ngenerated CLI/web clients.","properties":{"default_model":{"type":["string","null"],"description":"New default model id. `None` or an empty string clears the stored\nvalue so the CLI falls back to its own default."},"max_turns_analysis":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer analysis phase (1–200). `0`\nclears the stored value (built-in default applies); omitted/`None`\nleaves the current value unchanged — so a PATCH that only updates\n`default_model` doesn't wipe the turn settings."},"max_turns_feedback":{"type":["integer","null"],"format":"int32","description":"Default max turns for autofixer feedback rounds (1–200). `0` clears;\nomitted leaves unchanged."},"max_turns_fix":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer fix phase (1–200). `0` clears;\nomitted leaves unchanged."}}},"UpdateAiProviderResponse":{"type":"object","required":["provider_id"],"properties":{"default_model":{"type":["string","null"]},"max_turns_analysis":{"type":["integer","null"],"format":"int32"},"max_turns_feedback":{"type":["integer","null"],"format":"int32"},"max_turns_fix":{"type":["integer","null"],"format":"int32"},"provider_id":{"type":"string"}}},"UpdateAlertRuleRequest":{"type":"object","properties":{"cooldown_minutes":{"type":["integer","null"],"format":"int32"},"enabled":{"type":["boolean","null"]},"environment_filter":{"type":["integer","null"],"format":"int32"},"error_level_filter":{"type":["string","null"]},"name":{"type":["string","null"]},"notification_priority":{"type":["string","null"]},"trigger_config":{},"trigger_type":{"type":["string","null"]}}},"UpdateApiKeyRequest":{"type":"object","properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"]},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["projects:read","deployments:read"]}}},"UpdateAutomaticDeployRequest":{"type":"object","required":["automatic_deploy"],"properties":{"automatic_deploy":{"type":"boolean"}}},"UpdateBackupScheduleRequest":{"type":"object","description":"Request body for updating an existing backup schedule via `PATCH /api/backups/schedules/{id}`.\n\nAll fields are optional; only present fields are updated. Absent fields\nleave the corresponding column unchanged.","properties":{"description":{"type":["string","null"],"description":"New human-readable description. Pass an empty string `\"\"` to clear."},"enabled":{"type":["boolean","null"],"description":"Enable or disable the schedule. Skipped when `None`."},"include_control_plane":{"type":["boolean","null"],"description":"Toggle whether the control-plane backup is produced on every run."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Per-schedule wall-clock timeout override (seconds).\n\n- `None` (field absent) — leave current value unchanged\n- `Some(None)` (field present, JSON `null`) — clear override; fall back to engine default\n- `Some(Some(n))` — set to `n` seconds (must be >= 60)"},"name":{"type":["string","null"],"description":"New schedule name. Skipped when `None`. Must not be empty if provided."},"retention_period":{"type":["integer","null"],"format":"int32","description":"Days to retain backups produced by this schedule. Must be >= 1."},"schedule_expression":{"type":["string","null"],"description":"New cron expression. When changed, `next_run` is recomputed."},"tags":{"type":["array","null"],"items":{"type":"string"},"description":"Replace the full tag list. Skipped when `None`."},"target_all_services":{"type":["boolean","null"],"description":"Toggle between \"back up every database\" (`true`) and \"back up only\nthe explicit list\" (`false`). When set to `true`, the server clears\nthe explicit membership rows for this schedule."}}},"UpdateBlobRequest":{"type":"object","description":"Request to update Blob service configuration","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (e.g., \"rustfs/rustfs:1.0.0-alpha.98\")","example":"rustfs/rustfs:1.0.0-alpha.98"}}},"UpdateBlobResponse":{"type":"object","description":"Response after updating Blob service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service updated successfully"},"status":{"$ref":"#/components/schemas/BlobStatusResponse","description":"Current status"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"UpdateCloudflareProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/CloudflareConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateConfigBody":{"type":"object","properties":{"config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProviderConfig","description":"Typed provider configuration. Setting `config` to `null` clears\nthe stored config back to the accept-everything default. The\nconfig's `provider` tag must match the integration's provider."}]}}},"UpdateCustomDomainRequest":{"type":"object","properties":{"branch":{"type":["string","null"]},"domain":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to (empty string clears it)"},"status_code":{"type":["integer","null"],"format":"int32"}}},"UpdateDashboardRequest":{"type":"object","properties":{"layout":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DashboardLayout"}]},"name":{"type":["string","null"]}}},"UpdateDeploymentConfigRequest":{"type":"object","properties":{"automaticDeploy":{"type":["boolean","null"]},"cpuLimit":{"type":["integer","null"],"format":"int32"},"cpuRequest":{"type":["integer","null"],"format":"int32"},"exposedPort":{"type":["integer","null"],"format":"int32"},"memoryLimit":{"type":["integer","null"],"format":"int32"},"memoryRequest":{"type":["integer","null"],"format":"int32"},"performanceMetricsEnabled":{"type":["boolean","null"]},"replicas":{"type":["integer","null"],"format":"int32"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig"}]},"sessionRecordingEnabled":{"type":["boolean","null"]}}},"UpdateDeploymentTokenRequest":{"type":"object","properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"]},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["visitors:enrich","emails:send"]}}},"UpdateDnsProviderRequest":{"type":"object","description":"Request to update a DNS provider","properties":{"credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DnsProviderCredentials","description":"New credentials"}]},"description":{"type":["string","null"],"description":"New description"},"is_active":{"type":["boolean","null"],"description":"Active status"},"name":{"type":["string","null"],"description":"New name"}}},"UpdateEmailProviderRequest":{"type":"object","description":"Request body for `PATCH /email-providers/{id}`.\n\nAll fields are optional. Omit any field to leave it unchanged. The\n`provider_type` is immutable — to switch providers, delete the row and\ncreate a new one. For credentials, supplying any credential variant\nre-encrypts the stored blob; omitting them preserves the existing secret\n(so operators can rename without re-typing passwords).","properties":{"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"],"example":"My AWS SES"},"region":{"type":["string","null"],"example":"us-east-1"},"scaleway_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ScalewayCredentialsRequest"}]},"ses_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SesCredentialsRequest"}]},"smtp_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SmtpCredentialsRequest"}]},"sns_topic_arn":{"type":["string","null"],"description":"Rotate or clear the exact SNS topic allowed for this SES provider.\nOmit to preserve it, send `null` to clear it, or send a string to set it."}}},"UpdateEnvironmentSettingsRequest":{"type":"object","properties":{"anti_affinity":{"type":["boolean","null"],"description":"Anti-affinity: spread replicas across different nodes.\nWhen enabled, the scheduler avoids placing two replicas of the same\nenvironment on the same node. Defaults to `true`."},"attack_mode":{"type":["boolean","null"],"description":"Per-environment CAPTCHA attack-mode override (tri-state):\n- absent → leave the current override unchanged\n- JSON `null` → clear the override (inherit the project-level setting)\n- `true`/`false` → override the project setting for this environment"},"automatic_deploy":{"type":["boolean","null"],"description":"Enable/disable automatic deployments for this environment"},"branch":{"type":["string","null"]},"cpu_limit":{"type":["integer","null"],"format":"int32","description":"Maximum (limit) CPU in microcores. Send JSON `null` to clear → \"no limit\".\nAbsent leaves the current value unchanged."},"cpu_request":{"type":["integer","null"],"format":"int32","description":"Minimum (request) CPU in microcores. Send JSON `null` to clear (no request).\nAbsent leaves the current value unchanged."},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container (overrides project-level port for this environment)\n\nPriority order for port resolution:\n1. Image EXPOSE directive (auto-detected from built image)\n2. This environment-level exposed_port (overrides project setting)\n3. Project-level exposed_port (fallback)\n4. Default: 3000","example":8080},"force_https":{"type":["boolean","null"],"description":"Per-environment HTTP→HTTPS redirect override (tri-state):\n- absent → leave the current override unchanged\n- JSON `null` → clear the override (inherit the proxy default, which\n redirects only when the host has an active TLS certificate)\n- `true` → always redirect plain HTTP to HTTPS for this environment,\n even when no local certificate exists (TLS terminated upstream)\n- `false` → never redirect this environment, even when a certificate does\n exist\n\nRequests under `/.well-known/acme-challenge/` are never redirected\nregardless of this setting, so ACME HTTP-01 validation always completes."},"idle_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Seconds of inactivity before stopping containers (60-86400). Default: 300."},"memory_limit":{"type":["integer","null"],"format":"int32","description":"Maximum (limit) memory in MB. Send JSON `null` to clear → \"no limit\".\nAbsent leaves the current value unchanged."},"memory_request":{"type":["integer","null"],"format":"int32","description":"Minimum (request) memory in MB. Send JSON `null` to clear (no request).\nAbsent leaves the current value unchanged."},"on_demand":{"type":["boolean","null"],"description":"Enable on-demand mode (scale-to-zero). Containers are stopped after\nidle_timeout_seconds of no traffic and started on the next request."},"password":{"type":["string","null"],"description":"Set a password to protect this environment. The proxy will show an HTML\npassword form before allowing access. The password is bcrypt-hashed\nserver-side and never stored in plaintext.\nSend an empty string to remove password protection."},"performance_metrics_enabled":{"type":["boolean","null"],"description":"Enable/disable performance metrics collection"},"protected":{"type":["boolean","null"],"description":"When true, git pushes do NOT auto-deploy to this environment.\nDeployments must be promoted from another environment."},"replicas":{"type":["integer","null"],"format":"int32"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig","description":"Security configuration for this environment (overrides project-level settings)"}]},"session_recording_enabled":{"type":["boolean","null"],"description":"Enable/disable session recording"},"target_labels":{"description":"Label selector for node-based scheduling (overrides project-level setting).\nSame key with array value -> OR, different keys -> AND.\nExample: `{\"region\": [\"us\", \"asia\"], \"gpu\": \"true\"}`"},"target_nodes":{"type":["array","null"],"items":{"type":"integer","format":"int32"},"description":"Optional list of node IDs to deploy to (overrides project-level setting)"},"wake_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Max seconds to wait for containers to start on wake (5-120). Default: 30."}}},"UpdateEnvironmentSubdomainRequest":{"type":"object","description":"Request to rename an environment's auto-managed subdomain.\n\nThe subdomain is the host label inserted in front of the platform's\npreview domain (e.g. `myapp` in `myapp.preview.temps.sh`). Renaming\nreplaces the previous subdomain entirely — the old hostname stops\nresolving immediately after this request succeeds.","required":["subdomain"],"properties":{"subdomain":{"type":"string","description":"New subdomain label. Must be a DNS-safe slug (lowercase letters,\ndigits, and hyphens, 1-63 characters). The value is slugified\nserver-side, so casing and disallowed characters are normalized.","example":"myapp"}}},"UpdateEnvironmentVariableRequest":{"type":"object","required":["key","environment_ids"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean"},"is_secret":{"type":["boolean","null"],"description":"Optional secret-flag transition.\n- `Some(true)` promotes a regular var to a secret.\n- `Some(false)` is rejected if the row is already secret (one-way flag).\n- `None` (omitted) leaves the flag unchanged."},"key":{"type":"string"},"value":{"type":["string","null"],"description":"New plaintext value. `None` (omitted) keeps the existing ciphertext,\nwhich is the only way to edit a secret env var without re-typing its\nvalue (e.g. changing which environments it applies to)."}}},"UpdateErrorGroupRequest":{"type":"object","required":["status"],"properties":{"assigned_to":{"type":["string","null"]},"status":{"type":"string"}}},"UpdateExternalServiceRequest":{"type":"object","required":["parameters"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use for the service (e.g., \"gotempsh/postgres-walg:18-bookworm\", \"timescale/timescaledb-ha:pg18\")\nWhen provided, the service will be recreated with the new image while preserving data"},"parameters":{"type":"object","additionalProperties":{},"propertyNames":{"type":"string"}}}},"UpdateGitSettingsRequest":{"type":"object","required":["main_branch","repo_owner","repo_name","directory"],"properties":{"directory":{"type":"string"},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"],"description":"Git clone URL for public repositories"},"is_public_repo":{"type":["boolean","null"],"description":"Whether this is a public repository (no git provider connection needed)"},"main_branch":{"type":"string"},"preset":{"type":["string","null"]},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration (e.g., Dockerfile path for Docker preset)\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"repo_name":{"type":"string"},"repo_owner":{"type":"string"}}},"UpdateIncidentStatusRequest":{"type":"object","required":["status","message"],"properties":{"message":{"type":"string"},"status":{"type":"string"}}},"UpdateIpAccessControlRequest":{"type":"object","description":"Request to update an IP access control rule","properties":{"action":{"type":["string","null"],"description":"Optional new action"},"ip_address":{"type":["string","null"],"description":"Optional new IP address"},"reason":{"type":["string","null"],"description":"Optional new reason"}}},"UpdateKvRequest":{"type":"object","description":"Request to update KV service configuration","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (e.g., \"gotempsh/redis-walg:8-bookworm\")","example":"gotempsh/redis-walg:8-bookworm"}}},"UpdateKvResponse":{"type":"object","description":"Response after updating KV service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service updated successfully"},"status":{"$ref":"#/components/schemas/KvStatusResponse","description":"Current service status"},"success":{"type":"boolean","description":"Whether the operation succeeded"}}},"UpdateManagedDomainApiRequest":{"type":"object","description":"Request to update a managed domain's settings.","properties":{"auto_manage":{"type":["boolean","null"],"description":"Toggle automatic DNS management for this domain."},"generated_hostname_mode":{"type":["string","null"],"description":"`\"standard\"` or `\"flat\"`. Persisted as-is; switching to `\"flat\"` does not\nrecompute existing hostnames — use the apply endpoint for that."},"sync_generated_records":{"type":["boolean","null"],"description":"Toggle DNS record sync for this domain."}}},"UpdateMcpRequest":{"type":"object","required":["config"],"properties":{"config":{"type":"object"},"description":{"type":["string","null"]},"name":{"type":["string","null"]}}},"UpdateMetricAlertRequest":{"type":"object","properties":{"aggregation":{"type":["string","null"]},"detection_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DetectionConfig","description":"Replaces the detector wholesale when present (absent = leave unchanged)."}]},"dynamic_alerts":{"type":["boolean","null"],"description":"Toggles per-series (\"dynamic\") alerting (absent = leave unchanged)."},"enabled":{"type":["boolean","null"]},"for_duration_secs":{"type":["integer","null"],"format":"int32"},"group_by":{"type":["array","null"],"items":{"type":"string"},"description":"Replaces the group_by keys wholesale when present (absent = leave unchanged)."},"grouped_notification_threshold":{"type":["integer","null"],"format":"int32","description":"Updates the notification-grouping threshold (absent = leave unchanged)."},"label_filters":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"Replaces the label filters wholesale when present (absent = leave unchanged)."},"max_series":{"type":["integer","null"],"format":"int32","description":"Updates the dynamic-alerting cardinality cap (absent = leave unchanged)."},"metric_name":{"type":["string","null"]},"name":{"type":["string","null"]},"severity":{"type":["string","null"]},"window_secs":{"type":["integer","null"],"format":"int32"}}},"UpdateNotificationEmailProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/EmailConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateOidcProviderRequest":{"type":"object","properties":{"client_id":{"type":["string","null"]},"client_secret":{"type":["string","null"]},"default_role":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"group_claim":{"type":["string","null"]},"issuer_url":{"type":["string","null"]},"jit_provisioning":{"type":["boolean","null"]},"name":{"type":["string","null"]},"role_claim":{"type":["string","null"]},"scopes":{"type":["string","null"]},"template":{"type":["string","null"]},"trust_idp_email":{"type":["boolean","null"]}}},"UpdatePreferencesRequest":{"type":"object","required":["preferences"],"properties":{"preferences":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}},"UpdateProjectSecretRequest":{"type":"object","description":"Request to update a project secret. The `value` field is optional — omit it\nto rotate only the environment scoping / preview flag without touching the\nciphertext.","properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean"},"value":{"type":["string","null"],"description":"New plaintext value, <= 1 MiB. Omit to keep the existing value."}}},"UpdateProjectSettingsRequest":{"type":"object","properties":{"ai_alert_summaries_enabled":{"type":["boolean","null"],"description":"Opt in to AI summarization of metric alert notifications (ADR-021)."},"ai_debug_chat_enabled":{"type":["boolean","null"],"description":"Opt in to AI debugging chat, e.g. on deployment failures (ADR-023)."},"ai_write_actions_enabled":{"type":["boolean","null"],"description":"Opt in to AI propose-then-confirm write capability."},"attack_mode":{"type":["boolean","null"],"description":"Enable/disable attack mode (CAPTCHA protection) for all project environments"},"cross_project_trace_sharing":{"type":["boolean","null"],"description":"ADR-027 Phase 3 opt-out: set to false to suppress this project's traces\nfrom appearing in cross-project discovery results. Default true (consistent\nwith the OSS global-observability model). Omit to leave unchanged."},"directory":{"type":["string","null"]},"enable_preview_environments":{"type":["boolean","null"],"description":"Enable automatic preview environment creation for each branch"},"error_source_context_enabled":{"type":["boolean","null"],"description":"Opt in to native error-tracking source context (source-file upload +\nsource code shown in stack traces)."},"error_source_root":{"type":["string","null"],"description":"Set the auto-capture source root (relative to the checkout). Send an\nempty string to clear it back to the build-context default. Omit to\nleave unchanged."},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"main_branch":{"type":["string","null"]},"preset":{"type":["string","null"]},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration (e.g., Dockerfile path for Docker preset)\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"preview_envs_idle_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Idle timeout (seconds, 60..=86400) for on-demand preview environments."},"preview_envs_on_demand":{"type":["boolean","null"],"description":"When true, newly-created preview environments default to on-demand mode."},"preview_envs_wake_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Wake timeout (seconds, 5..=120) for on-demand preview environments."},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"slug":{"type":["string","null"]}}},"UpdateProviderCredentialsRequest":{"type":"object","description":"Partial-update payload for provider credentials. Every field is optional;\nonly the fields the user re-enters are applied. The server validates that\nthe fields supplied make sense for the provider's current auth_method\n(e.g. `app_id` + `private_key` only apply to GitHub Apps).","properties":{"app_id":{"type":["string","null"],"description":"Application ID (GitHub App integer as string; GitLab App string)."},"app_secret":{"type":["string","null"],"description":"GitLab App secret (not used by GitHub App — use `client_secret`)."},"client_id":{"type":["string","null"],"description":"OAuth client ID (GitLab OAuth, GitHub App)."},"client_secret":{"type":["string","null"],"description":"OAuth client secret (GitLab OAuth, GitHub App)."},"private_key":{"type":["string","null"],"description":"GitHub App private key (PEM)."},"redirect_uri":{"type":["string","null"],"description":"OAuth redirect URI (GitLab OAuth / GitLab App)."},"token":{"type":["string","null"],"description":"PAT for PAT-type providers."},"webhook_secret":{"type":["string","null"],"description":"GitHub App webhook secret."}}},"UpdateProviderKeyRequest":{"type":"object","properties":{"api_key":{"type":["string","null"]},"base_url":{"type":["string","null"],"description":"Double-Option: absent = leave unchanged, present-null = clear (revert to\nthe provider's default endpoint), present-value = set."},"default_model":{"type":["string","null"],"description":"Double-Option: absent = leave unchanged, present-null = clear the pinned\nmodel (revert to the per-provider default), present-value = set."},"display_name":{"type":["string","null"]},"is_active":{"type":["boolean","null"]}}},"UpdateProviderRequest":{"type":"object","properties":{"config":{},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateRouteRequest":{"type":"object","required":["host","port","enabled"],"properties":{"enabled":{"type":"boolean"},"host":{"type":"string"},"port":{"type":"integer","format":"int32"},"route_type":{"type":["string","null"],"description":"Route type: \"http\" (default) matches on HTTP Host header,\n\"tls\" matches on TLS SNI hostname for TCP passthrough"}}},"UpdateS3SourceRequest":{"type":"object","properties":{"access_key_id":{"type":["string","null"],"description":"Optional new access key ID","example":"AKIAXXXXXXXXXXXXXXXX"},"bucket_name":{"type":["string","null"],"description":"Optional new bucket name"},"bucket_path":{"type":["string","null"],"description":"Optional new bucket path"},"endpoint":{"type":["string","null"],"description":"Optional new endpoint URL for S3-compatible services","example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"],"description":"Optional new path-style addressing setting","example":true},"name":{"type":["string","null"],"description":"Optional new name for the source"},"region":{"type":["string","null"],"description":"Optional new region"},"secret_key":{"type":["string","null"],"description":"Optional new secret key"}}},"UpdateSecretBody":{"type":"object","required":["signing_secret"],"properties":{"signing_secret":{"type":"string","description":"New signing secret from the provider's dashboard. Encrypted at\nrest; never returned in any API response."}}},"UpdateSelfRequest":{"type":"object","properties":{"email":{"type":["string","null"],"example":"john.doe@example.com"},"name":{"type":["string","null"],"example":"John Doe"}}},"UpdateSessionDurationRequest":{"type":"object","required":["duration"],"properties":{"duration":{"type":"integer","format":"int32"}}},"UpdateSessionDurationResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"UpdateSkillRequest":{"type":"object","properties":{"content":{"type":["string","null"]},"description":{"type":["string","null"]},"name":{"type":["string","null"]}}},"UpdateSlackProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/SlackConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateSpeedMetricsPayload":{"type":"object","description":"Update speed metrics payload for late-loading metrics","properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"}}},"UpdateStatusResponse":{"type":"object","description":"Result of the background release-update check, driving the web console's\nupgrade banner. All optional fields are set together iff\n`update_available` is true.","required":["update_available","docs_url"],"properties":{"channel":{"type":["string","null"],"description":"Channel the install tracks: `stable` or `beta`."},"checked_at":{"type":["string","null"],"description":"When the check that found the update ran (ISO 8601, UTC)."},"current_version":{"type":["string","null"],"description":"Version tag of the running binary, e.g. `v0.1.0-beta.45`."},"docs_url":{"type":"string","description":"Docs page with upgrade instructions. Always present so the UI links\nthe same page regardless of update state."},"latest_version":{"type":["string","null"],"description":"Newest published tag on this install's channel."},"release_url":{"type":["string","null"],"description":"Release-notes page (GitHub release) for the newer version."},"update_available":{"type":"boolean","description":"True when a newer release than the running binary has been published\non this install's channel."}}},"UpdateTokenRequest":{"type":"object","required":["access_token"],"properties":{"access_token":{"type":"string"},"refresh_token":{"type":["string","null"]}}},"UpdateTokenResponse":{"type":"object","required":["connection_id","message","is_active"],"properties":{"connection_id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"message":{"type":"string"}}},"UpdateUserRequest":{"type":"object","properties":{"email":{"type":["string","null"],"example":"john.doe@example.com"},"name":{"type":["string","null"],"example":"John Doe"}}},"UpdateWebhookProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/WebhookConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateWebhookRequestBody":{"type":"object","properties":{"enabled":{"type":["boolean","null"],"description":"Whether the webhook is enabled"},"events":{"type":["array","null"],"items":{"type":"string"},"description":"Event types to subscribe to"},"secret":{"type":["string","null"],"description":"Secret for HMAC signature verification"},"url":{"type":["string","null"],"description":"Target URL for webhook delivery"}}},"UpgradeExternalServiceRequest":{"type":"object","required":["docker_image"],"properties":{"docker_image":{"type":"string","description":"Docker image to upgrade to (e.g., \"gotempsh/postgres-walg:18-bookworm\")\nThis will trigger pg_upgrade for PostgreSQL or equivalent upgrade procedures for other services","example":"gotempsh/postgres-walg:18-bookworm"}}},"UpgradeRequest":{"type":"object","required":["image"],"properties":{"image":{"type":"string","description":"Image reference to pull and run (e.g.\n`ghcr.io/gotempsh/temps-preview-gateway:latest`). Empty resets to default."}}},"UpsertAgentRequest":{"type":"object","properties":{"ai_model":{"type":["string","null"],"description":"Preferred model identifier for the CLI. `Some(\"\")` clears the stored value."},"ai_provider":{"type":["string","null"]},"ai_provider_key_id":{"type":["integer","null"],"format":"int32"},"api_key":{"type":["string","null"],"description":"Plain-text API key — will be encrypted before storage"},"branch_prefix":{"type":["string","null"]},"config_repo_branch":{"type":["string","null"],"description":"Branch of the config repo to use (default: \"main\")."},"config_repo_url":{"type":["string","null"],"description":"Private config repo containing .claude/ directory (skills, MCP, plugins)."},"cooldown_minutes":{"type":["integer","null"],"format":"int32"},"daily_budget_cents":{"type":["integer","null"],"format":"int32"},"deliverable":{"type":["string","null"]},"description":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"max_turns":{"type":["integer","null"],"format":"int32"},"mcp_servers_config":{"description":"MCP servers config (Claude Code settings.json mcpServers format).\nCredential-bearing legacy inline objects are write-only: normal reads\nmask them, and updates must omit this field to preserve existing values."},"name":{"type":["string","null"]},"prompt":{"type":["string","null"]},"sandbox_enabled":{"type":["boolean","null"]},"skills_config":{"description":"Skills config as JSON array."},"slug":{"type":["string","null"]},"timeout_seconds":{"type":["integer","null"],"format":"int32"},"tools_config":{"description":"Tools config as JSON array. Custom-tool webhook URLs and headers are\nwrite-only; omit this field on update to preserve them."},"trigger_config":{"description":"Trigger configuration JSON: { \"error\": { \"new_issue\": true, \"regression\": true }, \"manual\": true }"}}},"UpsertSecretRequest":{"type":"object","required":["name","value"],"properties":{"description":{"type":["string","null"]},"mount_path":{"type":["string","null"],"description":"Required for \"file\" type secrets — absolute path inside the sandbox"},"name":{"type":"string"},"secret_type":{"type":"string","description":"\"env\" (environment variable) or \"file\" (written to mount_path)"},"value":{"type":"string"}}},"UptimeDataPoint":{"type":"object","required":["timestamp","status"],"properties":{"error_message":{"type":["string","null"]},"response_time_ms":{"type":["integer","null"],"format":"int32"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"UptimeHistoryResponse":{"type":"object","required":["monitor_id","uptime_data"],"properties":{"monitor_id":{"type":"integer","format":"int32"},"uptime_data":{"type":"array","items":{"$ref":"#/components/schemas/UptimeDataPoint"}}}},"UsageFilter":{"type":"object","description":"Filters for querying AI usage data.\n\nCost bounds are expressed in microcents (the unit stored in\n`estimated_cost_microcents`). At most one of `gte`/`gt` and one of\n`lte`/`lt` is meaningful per query; if both are set the stricter wins\nnaturally because they are ANDead together.","properties":{"conversation_id":{"type":["string","null"]},"cost_gt":{"type":["integer","null"],"format":"int64","description":"Cost strictly greater-than, in microcents."},"cost_gte":{"type":["integer","null"],"format":"int64","description":"Cost greater-than-or-equal, in microcents."},"cost_lt":{"type":["integer","null"],"format":"int64","description":"Cost strictly less-than, in microcents."},"cost_lte":{"type":["integer","null"],"format":"int64","description":"Cost less-than-or-equal, in microcents."},"model":{"type":["string","null"]},"provider":{"type":["string","null"]},"status":{"type":["integer","null"],"format":"int32","description":"Filter by HTTP status code (exact match)."},"tags":{"type":["string","null"],"description":"Comma-separated tags to filter by (AND logic)."},"tokens_gt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly greater-than."},"tokens_gte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) greater-than-or-equal."},"tokens_lt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly less-than."},"tokens_lte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) less-than-or-equal."},"user_id":{"type":["integer","null"],"format":"int32"}}},"UsageInfo":{"type":"object","required":["prompt_tokens","completion_tokens","total_tokens"],"properties":{"completion_tokens":{"type":"integer","format":"int64"},"prompt_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"UsageLogEntry":{"type":"object","required":["id","timestamp","provider","model","input_tokens","output_tokens","latency_ms","estimated_cost_microcents","status","is_streaming","is_byok","tags"],"properties":{"conversation_id":{"type":["string","null"]},"estimated_cost_microcents":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int64"},"input_tokens":{"type":"integer","format":"int64"},"is_byok":{"type":"boolean"},"is_streaming":{"type":"boolean"},"latency_ms":{"type":"integer","format":"int32"},"model":{"type":"string"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_id":{"type":["string","null"]},"status":{"type":"integer","format":"int32"},"tags":{"type":"array","items":{"type":"string"}},"timestamp":{"type":"string"},"trace_id":{"type":["string","null"]}}},"UsageLogPage":{"type":"object","description":"A page of recent usage log entries plus the total count for pagination.","required":["entries","total"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/UsageLogEntry"},"description":"The usage log entries for the requested page."},"total":{"type":"integer","format":"int64","description":"Total number of entries matching the filter (across all pages)."}}},"UsageQueryParams":{"type":"object","properties":{"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"model":{"type":["string","null"],"description":"Filter by model name"},"provider":{"type":["string","null"],"description":"Filter by provider name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"UsageSource":{"type":"string","description":"How the \"actual usage\" numbers were obtained","enum":["metrics-api","requests-only","unavailable"]},"UsageSummary":{"type":"object","required":["total_requests","total_input_tokens","total_output_tokens","total_tokens","avg_latency_ms","total_cost_microcents","error_count","streaming_count","byok_count"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"byok_count":{"type":"integer","format":"int64"},"error_count":{"type":"integer","format":"int64"},"streaming_count":{"type":"integer","format":"int64"},"total_cost_microcents":{"type":"integer","format":"int64"},"total_input_tokens":{"type":"integer","format":"int64"},"total_output_tokens":{"type":"integer","format":"int64"},"total_requests":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"UserResponse":{"type":"object","required":["id","username","name","avatar_url","mfa_enabled","role"],"properties":{"avatar_url":{"type":"string"},"email":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"role":{"type":"string","description":"User's role (e.g., \"admin\", \"user\", \"demo\")"},"username":{"type":"string"}}},"ValidateEmailRequest":{"type":"object","description":"Request body for validating an email address","required":["email"],"properties":{"email":{"type":"string","description":"Email address to validate","example":"someone@gmail.com"},"proxy":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProxyRequest","description":"Optional SOCKS5 proxy configuration"}]}}},"ValidateEmailResponse":{"type":"object","description":"Complete email validation response","required":["email","is_reachable","syntax","mx","misc","smtp"],"properties":{"email":{"type":"string","description":"The email address that was validated","example":"someone@gmail.com"},"is_reachable":{"$ref":"#/components/schemas/ReachabilityStatus","description":"Overall reachability status: safe, risky, invalid, or unknown"},"misc":{"$ref":"#/components/schemas/MiscResult","description":"Miscellaneous validation result"},"mx":{"$ref":"#/components/schemas/MxResult","description":"MX record validation result"},"smtp":{"$ref":"#/components/schemas/SmtpResult","description":"SMTP validation result"},"syntax":{"$ref":"#/components/schemas/SyntaxResult","description":"Syntax validation result"}}},"ValidationLevel":{"type":"string","description":"Validation severity level","enum":["info","warning","error","critical"]},"ValidationReport":{"type":"object","description":"Complete validation report","required":["results","overall_status","summary"],"properties":{"overall_status":{"$ref":"#/components/schemas/ValidationStatus","description":"Overall status"},"results":{"type":"array","items":{"$ref":"#/components/schemas/ValidationResult"},"description":"All validation results"},"summary":{"$ref":"#/components/schemas/ValidationSummary","description":"Summary statistics"}}},"ValidationResponse":{"type":"object","required":["connection_id","is_valid","message"],"properties":{"connection_id":{"type":"integer","format":"int32"},"is_valid":{"type":"boolean"},"message":{"type":"string"}}},"ValidationResult":{"type":"object","description":"Result of a validation check","required":["rule_id","rule_name","level","passed","message","affected_resources"],"properties":{"affected_resources":{"type":"array","items":{"type":"string"},"description":"Affected resources/fields"},"level":{"$ref":"#/components/schemas/ValidationLevel","description":"Validation level"},"message":{"type":"string","description":"Message describing the result"},"passed":{"type":"boolean","description":"Whether the validation passed"},"remediation":{"type":["string","null"],"description":"Suggested remediation (if failed)"},"rule_id":{"type":"string","description":"Rule that was checked"},"rule_name":{"type":"string","description":"Human-readable rule name"}}},"ValidationStatus":{"type":"string","description":"Overall validation status","enum":["passed","passed-with-warnings","failed-with-warnings","failed"]},"ValidationSummary":{"type":"object","description":"Validation summary statistics","required":["total_count","passed_count","failed_count","info_count","warning_count","error_count","critical_count"],"properties":{"critical_count":{"type":"integer","description":"Critical-level results","minimum":0},"error_count":{"type":"integer","description":"Error-level results","minimum":0},"failed_count":{"type":"integer","description":"Validations that failed","minimum":0},"info_count":{"type":"integer","description":"Info-level results","minimum":0},"passed_count":{"type":"integer","description":"Validations that passed","minimum":0},"total_count":{"type":"integer","description":"Total validations run","minimum":0},"warning_count":{"type":"integer","description":"Warning-level results","minimum":0}}},"VerifyMfaRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"ViewItem":{"type":"object","required":["label","value"],"properties":{"label":{"type":"string","format":"date-time"},"value":{"type":"integer","format":"int64"}}},"ViewsOverTime":{"type":"object","required":["items","metric","present_index"],"properties":{"comparison_labels":{"type":["array","null"],"items":{"type":"string"}},"comparison_plot":{"type":["array","null"],"items":{"type":"integer","format":"int64"}},"full_intervals":{"type":["array","null"],"items":{"type":"string"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/ViewItem"}},"metric":{"type":"string"},"present_index":{"type":"integer","minimum":0}}},"ViewsOverTimeQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"VisitorDetails":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorFacetValue":{"type":"object","description":"A single facet value with its visitor count. Used to populate filter\ndropdowns on the visitors page (e.g. \"Germany — 1,234 visitors\").","required":["value","count"],"properties":{"code":{"type":["string","null"],"description":"Optional secondary code for the value. Currently only populated for\nthe `country` facet, where it carries the 2-letter ISO country code\nso the UI can render a flag without re-mapping."},"count":{"type":"integer","format":"int64","description":"Distinct visitor count matching this value in the current segment."},"value":{"type":"string","description":"The dimension value (e.g. \"United States\", \"Chrome\", \"google.com\").\n`None` is encoded as the literal string \"Direct\" for referrer and as\nthe empty string for the rest."}}},"VisitorFacets":{"type":"object","description":"All filter dropdown contents in one response. Each list is the top N\nvalues for that dimension within the current date range and segment\n(excluding the dimension being queried so the dropdown still shows\nalternatives when a value is already selected).","required":["country","region","city","channel","referrer"],"properties":{"channel":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"city":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"country":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"referrer":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"region":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}}}},"VisitorFacetsQuery":{"allOf":[{"$ref":"#/components/schemas/VisitorSegmentFilters"},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"has_activity_only":{"type":["boolean","null"]},"include_crawlers":{"type":["boolean","null"]},"per_facet_limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of values returned per dimension (default: 50, max: 200)."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}],"description":"Query parameters for the visitor-facets endpoint. Mirrors the shape of\n`VisitorsListQuery` so the same segment filters apply — facet counts are\nalways computed against the *currently filtered* visitor pool, minus the\ndimension being aggregated."},"VisitorInfo":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"current_page":{"type":["string","null"],"description":"Most recent page path visited by this visitor"},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorJourneyQuery":{"type":"object","required":["project_id"],"properties":{"limit_sessions":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"VisitorJourneyResponse":{"type":"object","description":"Complete visitor journey response","required":["visitor_id","total_sessions","total_events","sessions"],"properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/JourneySession"},"description":"Sessions with their events, ordered newest first"},"total_events":{"type":"integer","format":"int64","description":"Total number of events across all sessions"},"total_sessions":{"type":"integer","format":"int64","description":"Total number of sessions"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor internal ID"}}},"VisitorLocationsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"granularity":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LocationGranularity"}]},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"VisitorRecord":{"type":"object","required":["id","visitor_id","project_id","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"custom_data":{},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"visitor_id":{"type":"string"}}},"VisitorSegmentFilters":{"type":"object","description":"Optional segment filters for [`VisitorsListQuery`]. Each filter narrows the\nresult set to visitors who match the given dimension value within the date\nrange. All filters resolve against `visitor` / `ip_geolocations` — by\ndesign we never touch the events hypertable here so filtering stays fast\nregardless of event volume.","properties":{"filter_channel":{"type":["string","null"],"description":"First-touch marketing channel (matches `visitor.first_channel`)"},"filter_city":{"type":["string","null"],"description":"Geolocation city (matches `ip_geolocations.city`)"},"filter_country":{"type":["string","null"],"description":"Geolocation country (matches `ip_geolocations.country`)"},"filter_referrer":{"type":["string","null"],"description":"First-touch referrer hostname (matches `visitor.first_referrer_hostname`)"},"filter_region":{"type":["string","null"],"description":"Geolocation region (matches `ip_geolocations.region`)"}}},"VisitorSessionsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"VisitorSessionsResponse":{"type":"object","required":["visitor_id","sessions","total_sessions"],"properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionSummary"}},"total_sessions":{"type":"integer","format":"int64"},"visitor_id":{"type":"string"}}},"VisitorStats":{"type":"object","required":["visitor_id","first_seen","last_seen","total_sessions","total_page_views","total_events","average_session_duration","bounce_rate","engagement_rate","top_pages","top_referrers","devices_used","locations"],"properties":{"average_session_duration":{"type":"number","format":"double"},"bounce_rate":{"type":"number","format":"double"},"devices_used":{"type":"array","items":{"type":"string"}},"engagement_rate":{"type":"number","format":"double"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"locations":{"type":"array","items":{"$ref":"#/components/schemas/LocationInfo"}},"top_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageVisit"}},"top_referrers":{"type":"array","items":{"type":"string"}},"total_events":{"type":"integer","format":"int64"},"total_page_views":{"type":"integer","format":"int64"},"total_sessions":{"type":"integer","format":"int64"},"visitor_id":{"type":"integer","format":"int32"}}},"VisitorWithGeolocation":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorsListQuery":{"allOf":[{"$ref":"#/components/schemas/VisitorSegmentFilters"},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"has_activity_only":{"type":["boolean","null"],"description":"Filter to only include visitors with recorded activity (events/sessions).\nWhen true, excludes \"ghost\" visitors that have no events."},"include_crawlers":{"type":["boolean","null"]},"limit":{"type":["integer","null"],"format":"int32"},"offset":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"VisitorsResponse":{"type":"object","required":["visitors","total_count","filtered_count"],"properties":{"filtered_count":{"type":"integer","format":"int64"},"total_count":{"type":"integer","format":"int64"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/VisitorInfo"}}}},"VolumeMount":{"type":"object","description":"Volume mount in deployment","required":["source","destination","read_only","type"],"properties":{"destination":{"type":"string","description":"Destination path in container"},"read_only":{"type":"boolean","description":"Read-only flag"},"source":{"type":"string","description":"Source (volume name or path)"},"type":{"$ref":"#/components/schemas/VolumeType","description":"Volume type"}}},"VolumeType":{"type":"string","description":"Volume type","enum":["bind","volume","tmpfs"]},"VulnerabilityResponse":{"type":"object","required":["id","scan_id","vulnerability_id","package_name","installed_version","severity","title","created_at"],"properties":{"class":{"type":["string","null"],"example":"os-pkgs"},"created_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"cvss_score":{"type":["number","null"],"format":"float"},"description":{"type":["string","null"]},"fixed_version":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"installed_version":{"type":"string"},"last_modified_date":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"package_name":{"type":"string"},"primary_url":{"type":["string","null"]},"published_date":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"references":{},"scan_id":{"type":"integer","format":"int32"},"severity":{"type":"string"},"target":{"type":["string","null"],"example":"alpine:3.18 (alpine 3.18.0)"},"title":{"type":"string"},"type":{"type":["string","null"],"example":"alpine"},"vulnerability_id":{"type":"string"}}},"WalWarning":{"oneOf":[{"type":"object","description":"`pg_wal` is significantly larger than `max_wal_size`.","required":["pg_wal_bytes","max_wal_size_bytes","ratio","kind"],"properties":{"kind":{"type":"string","enum":["wal_bloat"]},"max_wal_size_bytes":{"type":"integer","format":"int64"},"pg_wal_bytes":{"type":"integer","format":"int64"},"ratio":{"type":"number","format":"double"}}},{"type":"object","description":"A replication slot is holding WAL it's not consuming.","required":["slot_name","retained_bytes","active","kind"],"properties":{"active":{"type":"boolean"},"kind":{"type":"string","enum":["stale_slot"]},"retained_bytes":{"type":"integer","format":"int64"},"slot_name":{"type":"string"}}},{"type":"object","description":"`archive_status/*.ready` count exceeds threshold — `archive_command`\nis either failing or running slower than WAL generation.","required":["ready_count","kind"],"properties":{"kind":{"type":"string","enum":["archive_backlog"]},"ready_count":{"type":"integer","format":"int64"}}},{"type":"object","description":"`archive_mode = on` but `archive_command` is empty / `/bin/true`.\nWAL accumulates forever waiting for a destination that never accepts.","required":["kind"],"properties":{"kind":{"type":"string","enum":["archive_mode_without_command"]}}},{"type":"object","description":"Oldest WAL segment is older than `WAL_NOT_RECYCLED_AGE_SECS`.\nIndependent signal: something is blocking recycling even if total\nsize hasn't exploded yet.","required":["oldest_age_secs","kind"],"properties":{"kind":{"type":"string","enum":["wal_not_recycled"]},"oldest_age_secs":{"type":"integer","format":"int64"}}}],"description":"One actionable warning surfaced to the UI.\n\nEach variant carries the data needed to render a remediation hint without\nthe frontend re-querying anything."},"WalWarningSeverity":{"type":"string","enum":["warning","critical"]},"WebhookConfig":{"type":"object","description":"Configuration for a generic webhook notification provider","required":["url"],"properties":{"headers":{"type":"object","description":"Custom headers to include in the request (e.g., for authentication tokens)","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"},"example":{"Authorization":"Bearer your-token","X-Custom-Header":"custom-value"}},"method":{"type":"string","description":"HTTP method to use (POST, PUT, PATCH). Defaults to POST.","example":"POST"},"timeout_secs":{"type":"integer","format":"int64","description":"Request timeout in seconds. Defaults to 30.","example":30,"minimum":0},"url":{"type":"string","description":"The URL to send webhook requests to","example":"https://api.example.com/notifications"}}},"WebhookDeliveryResponse":{"type":"object","required":["id","webhook_id","event_type","event_id","payload","success","attempt_number","created_at"],"properties":{"attempt_number":{"type":"integer","format":"int32"},"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"delivered_at":{"type":["string","null"],"format":"date-time"},"error_message":{"type":["string","null"]},"event_id":{"type":"string"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int32"},"payload":{"type":"string","description":"JSON payload that was sent to the webhook endpoint","example":{"event_type":"deployment.succeeded","data":{"deployment_id":123}}},"status_code":{"type":["integer","null"],"format":"int32"},"success":{"type":"boolean"},"webhook_id":{"type":"integer","format":"int32"}}},"WebhookResponse":{"type":"object","required":["id","project_id","url","events","enabled","has_secret","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"enabled":{"type":"boolean"},"events":{"type":"array","items":{"type":"string"}},"has_secret":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"url":{"type":"string"}}},"WebhookTriggerRequest":{"allOf":[{"description":"Arbitrary JSON payload from the caller. Passed to the agent as user_context."}]},"WebhookTriggerResponse":{"type":"object","required":["run_id","status"],"properties":{"run_id":{"type":"integer","format":"int32"},"status":{"type":"string"}}},"WorkflowDryRunRequest":{"type":"object","required":["yaml"],"properties":{"cpu_limit":{"type":["number","null"],"format":"double","description":"Optional CPU override applied after parsing YAML (clamped server-side).\nWhen `Some`, this takes precedence over `cpu_limit` inside the YAML —\nlets the CLI pass `--cpu` without rewriting the YAML text."},"error_group_id":{"type":["integer","null"],"format":"int32","description":"Optional error group to link this dry-run to. When set, the executor's\n`load_error_context` path injects `{{error_type}}` / `{{error_message}}`\n/ `{{stack_trace}}` into the prompt — same behaviour as a committed\nworkflow triggered with `trigger_source_type = \"error_group\"`. Must\nbelong to `project_id` (handler enforces)."},"memory_limit_mb":{"type":["integer","null"],"format":"int64","description":"Optional memory override in MB (clamped server-side). Same precedence\nrule as `cpu_limit`.","minimum":0},"user_context":{"type":["string","null"],"description":"Optional context appended to the prompt (e.g. \"test against staging\nonly\"). Mirrors `TriggerAgentRequest.user_context`."},"yaml":{"type":"string","description":"Full WorkflowYamlConfig as YAML text. Server validates and re-serializes\nbefore storing on the run row."}}},"WorkloadDescriptor":{"type":"object","description":"Brief descriptor for discovered workloads (used in listing)","required":["id","workload_type","status","labels"],"properties":{"created_at":{"type":["string","null"],"format":"date-time","description":"Creation timestamp"},"id":{"$ref":"#/components/schemas/WorkloadId","description":"Unique ID in source system"},"image":{"type":["string","null"],"description":"Image/build reference (for containers)"},"labels":{"type":"object","description":"Labels/tags from source system","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":["string","null"],"description":"Workload name (if any)"},"status":{"$ref":"#/components/schemas/WorkloadStatus","description":"Current status"},"workload_type":{"$ref":"#/components/schemas/WorkloadType","description":"Workload type (container, function, static-site, etc.)"}}},"WorkloadId":{"type":"string","description":"Unique identifier for a workload in the source system"},"WorkloadStatus":{"type":"string","description":"Workload status in source system","enum":["running","paused","stopped","exited","failed","deployed","building","unknown"]},"WorkloadType":{"type":"string","description":"Workload type","enum":["container","function","static-site","server-side-app","worker","database","message-queue","cache","cron-job","other"]},"WriteFileBody":{"type":"object","required":["path","contents_b64"],"properties":{"contents_b64":{"type":"string","description":"File contents, base64-encoded. Required — lets callers ship binary\ndata over JSON without charset games."},"mode":{"type":["integer","null"],"format":"int32","description":"Unix permission mask (e.g. 0o644). Defaults to 0o644 when absent.","minimum":0},"path":{"type":"string","description":"Absolute path inside the sandbox. Must start with `/`."}},"additionalProperties":false},"WriteFilesBody":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/WriteFileBody"},"description":"List of files to write. Each entry must include an absolute\n`path` and base64-encoded `contents_b64`. Empty list is a no-op."}},"additionalProperties":false},"WriteFilesResponse":{"type":"object","required":["written"],"properties":{"written":{"type":"integer","description":"Number of files successfully written before the first failure\n(if any). On full success this equals `files.len()`.","minimum":0}}},"ZoneListResponse":{"type":"object","description":"Zone list response","required":["zones"],"properties":{"zones":{"type":"array","items":{"$ref":"#/components/schemas/DnsZone"}}}}},"securitySchemes":{"bearer_auth":{"type":"http","scheme":"bearer","description":"Bearer token authentication. Use format: `Bearer `. Supports API keys (starting with `tk_`), CLI tokens, and session tokens."}}},"tags":[{"name":"Events","description":"Analytics events tracking endpoints"},{"name":"Metrics","description":"Analytics metrics collection endpoints including performance web vitals"},{"name":"Funnels","description":"Funnel management endpoints"},{"name":"Analytics","description":"Analytics and session replay management"},{"name":"Performance","description":"Performance metrics management"},{"name":"geo","description":"Geolocation API endpoints"},{"name":"Platform","description":"Platform information and compatibility"},{"name":"Git Providers","description":"Git provider management endpoints"},{"name":"Repositories","description":"Repository management endpoints"},{"name":"Public Repositories","description":"Endpoints for accessing public repositories without authentication. Supports GitHub and GitLab."},{"name":"Notification Providers","description":"Notification provider management endpoints"},{"name":"Notification Preferences","description":"User notification preferences and settings"},{"name":"DNS Providers","description":"DNS provider management endpoints"},{"name":"Internal DNS","description":"Per-node DNS resolver sync (ADR-011)"},{"name":"Domains","description":"Domain management endpoints"},{"name":"Email Providers","description":"Email provider management endpoints"},{"name":"Email Domains","description":"Email domain management and verification"},{"name":"Emails","description":"Email sending and retrieval"},{"name":"Email Tracking","description":"Email open and click tracking"},{"name":"Email Validation","description":"Email address validation and verification"},{"name":"Webhooks","description":"Webhook management endpoints"},{"name":"Webhook Deliveries","description":"Webhook delivery history and retry endpoints"},{"name":"External Services","description":"External service integration endpoints"},{"name":"External Services - Query","description":"Data querying and exploration endpoints"},{"name":"Metrics","description":"Time-series metrics and alert rule endpoints"},{"name":"KV Store","description":"Key-Value storage operations"},{"name":"KV Management","description":"KV service management operations"},{"name":"Blob","description":"Blob storage operations"},{"name":"Blob Management","description":"Blob service management operations"},{"name":"Environments","description":"Environment management operations"},{"name":"Secrets","description":"File-mounted secrets (/run/secrets/)"},{"name":"Projects","description":"Project management endpoints"},{"name":"Presets","description":"Available deployment presets"},{"name":"Templates","description":"Project template endpoints"},{"name":"Custom Domains","description":"Custom domain management for projects"},{"name":"error-tracking","description":"Error tracking data fetching endpoints"},{"name":"Vulnerability Scans","description":"Vulnerability scan management endpoints"},{"name":"Agents","description":"Autonomous AI agents, autofixer (interactive AI debugging), skills/MCP definitions, and preview gateway management."},{"name":"Crons","description":"Cron jobs management API"},{"name":"Sandboxes","description":"Standalone sandbox API (`/v1/sandboxes/*`) for running isolated containers."},{"name":"Logs","description":"Log search, context, live tail, and retention management"},{"name":"Imports","description":"Import workloads from external sources"},{"name":"Status Page","description":"Status page and monitoring endpoints"},{"name":"OTel Ingest","description":"OTLP/HTTP ingest endpoints (protobuf)"},{"name":"OTel","description":"Query endpoints for the monitoring UI"},{"name":"GenAI","description":"GenAI agent activity tracing endpoints"},{"name":"Alarms","description":"Unified alarm history — list, summarise, acknowledge, resolve"},{"name":"Authentication","description":"Authentication and authorization endpoints"},{"name":"Users","description":"User management endpoints"},{"name":"Backups","description":"Backup management endpoints"},{"name":"Restore","description":"External service restore operations"},{"name":"Revenue","description":"Per-project revenue tracking integrations and analytics"},{"name":"Observability","description":"Unified observability event stream — runtime logs, requests, spans, errors, revenue"},{"name":"AI Gateway","description":"OpenAI-compatible chat, embeddings, and model endpoints"},{"name":"AI Gateway Admin","description":"Provider key management endpoints"},{"name":"AI Gateway Usage","description":"Usage analytics and reporting endpoints"},{"name":"AI Gateway Pricing","description":"Model pricing endpoints"},{"name":"API Keys","description":"API key management endpoints"},{"name":"Load Balancer","description":"Load balancer management endpoints"},{"name":"IP Access Control","description":"IP access control management endpoints"},{"name":"Files","description":"Static file serving endpoints"},{"name":"External Plugins","description":"External plugin management and discovery"}]} +{"openapi":"3.1.0","info":{"title":"Temps","description":"An API for managing projects, deployments, and infrastructure resources","contact":{"name":"Temps Support","url":"https://temps.sh"},"version":"1.0.0"},"servers":[{"url":"/api","description":"Base path for all API endpoints"}],"paths":{"/.well-known/temps.json":{"get":{"tags":["Platform"],"summary":"Get platform information","operationId":"get_platform_info","responses":{"200":{"description":"Successfully retrieved platform information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformInfo"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/0/organizations/{org_slug}/chunk-upload/":{"get":{"tags":["sentry-compat"],"summary":"Chunk upload options (stub for sentry-cli compatibility).","description":"sentry-cli checks this endpoint to determine if chunk-based upload is supported.\nWe return a response indicating that chunk upload is NOT supported, which forces\nsentry-cli to fall back to the standard file-by-file upload.","operationId":"chunk_upload_options","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Chunk upload options","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryChunkUploadResponse"}}}}}}},"/0/organizations/{org_slug}/releases/":{"post":{"tags":["sentry-compat"],"summary":"Create a release (stub for sentry-cli compatibility).","description":"sentry-cli calls this before uploading files. Since Temps implicitly creates\nreleases when source maps are uploaded, this is a no-op that returns the\nexpected response format.","operationId":"create_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored in single-tenant mode)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryCreateReleaseRequest"}}},"required":true},"responses":{"201":{"description":"Release created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"}}}},"/0/projects/{org_slug}/{project_slug}/releases/":{"post":{"tags":["sentry-compat"],"summary":"Create a release for a specific project (stub for sentry-cli compatibility).","description":"sentry-cli calls this endpoint (instead of /organizations/.../releases/) when\nboth SENTRY_ORG and SENTRY_PROJECT env vars are set. Behaves identically to\nthe organizations endpoint but validates the project slug.","operationId":"create_project_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored in single-tenant mode)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryCreateReleaseRequest"}}},"required":true},"responses":{"201":{"description":"Release created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}}},"/0/projects/{org_slug}/{project_slug}/releases/{version}/":{"put":{"tags":["sentry-compat"],"summary":"Finalize a release (stub for sentry-cli compatibility).","description":"sentry-cli calls `releases finalize` after uploading source maps. This sets\nthe dateReleased on the release. Since Temps stores source maps independently\nof releases, this is a no-op that returns the expected response.","operationId":"finalize_project_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version to finalize","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Release finalized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}}},"/0/projects/{org_slug}/{project_slug}/releases/{version}/files/":{"get":{"tags":["sentry-compat"],"summary":"List files for a release.","description":"Returns all source maps stored for a specific release in sentry-cli compatible format.","operationId":"list_release_files","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of release files","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SentryReleaseFileResponse"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}},"post":{"tags":["sentry-compat"],"summary":"Upload a source map file for a release.","description":"Accepts the same multipart format as the Sentry release files API.\nThe `name` field should be the URL path of the file (e.g., `~/dist/bundle.js.map`).\n\nThe route has a 50 MiB body limit applied at the router level (Fix #4).\nA per-field size check provides an additional defense-in-depth layer.","operationId":"upload_release_file","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"File uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseFileResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"},"413":{"description":"Source map file exceeds the 50 MiB per-field limit"}}}},"/_temps/event":{"post":{"tags":["Metrics"],"summary":"Record analytics event","operationId":"record_event_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Event recorded successfully"},"400":{"description":"Bad request"},"500":{"description":"Internal server error"}}}},"/_temps/session-replay/events":{"post":{"tags":["Analytics"],"summary":"Add events to existing session replay","operationId":"add_session_replay_events","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayEventsRequest"}}},"required":true},"responses":{"200":{"description":"Events added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/session-replay/init":{"post":{"tags":["Analytics"],"summary":"Initialize session replay with metadata","operationId":"init_session_replay","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayInitRequest"}}},"required":true},"responses":{"201":{"description":"Session initialized successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayInitResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/speed":{"post":{"tags":["Performance"],"summary":"Record performance metrics from client","operationId":"record_speed_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeedMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Metrics recorded successfully"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Host not found in route table","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/speed/update":{"post":{"tags":["Performance"],"summary":"Update late performance metrics","operationId":"update_speed_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSpeedMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Metrics updated successfully"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Host not found or metrics not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/admin/gate-settings":{"get":{"tags":["AdminGate"],"operationId":"get_admin_gate","responses":{"200":{"description":"Current admin gate config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AdminGate"],"operationId":"patch_admin_gate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAdminGateRequest"}}},"required":true},"responses":{"200":{"description":"Updated admin gate config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGateResponse"}}}},"400":{"description":"Invalid IP/CIDR/host"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Env-overridden or would lock out caller"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers":{"get":{"tags":["Authentication"],"operationId":"list_oidc_providers","responses":{"200":{"description":"OIDC providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Authentication"],"operationId":"create_oidc_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOidcProviderRequest"}}},"required":true},"responses":{"201":{"description":"OIDC provider created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProviderResponse"}}}},"409":{"description":"Another OIDC provider already uses that name"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}":{"delete":{"tags":["Authentication"],"operationId":"delete_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"OIDC provider deleted"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Authentication"],"operationId":"update_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOidcProviderRequest"}}},"required":true},"responses":{"200":{"description":"OIDC provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProviderResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/role-mappings":{"get":{"tags":["Authentication"],"operationId":"list_oidc_role_mappings","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"OIDC role mappings","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcRoleMappingResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Authentication"],"operationId":"create_oidc_role_mapping","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOidcRoleMappingRequest"}}},"required":true},"responses":{"201":{"description":"Role mapping created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRoleMappingResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/test":{"post":{"tags":["Authentication"],"operationId":"test_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcTestConnectionResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/users":{"get":{"tags":["Authentication"],"operationId":"list_oidc_provider_users","parameters":[{"name":"provider_id","in":"path","description":"OIDC provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Users authenticated via this OIDC provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderUserResponse"}}}}},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/role-mappings/{mapping_id}":{"delete":{"tags":["Authentication"],"operationId":"delete_oidc_role_mapping","parameters":[{"name":"mapping_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Role mapping deleted"}},"security":[{"bearer_auth":[]}]}},"/agents/webhook/{webhook_id}":{"post":{"tags":["Agents"],"summary":"Public webhook endpoint. Authenticated via `X-Webhook-Token` header.","description":"`POST /api/agents/webhook/{webhook_id}`\nHeader: `X-Webhook-Token: `\n\nThe `webhook_id` in the URL is a short non-secret identifier (safe to log).\nThe actual credential is the secret token in the header.\n\nAccepts any JSON body, which is passed as `user_context` to the agent run.","operationId":"webhook_trigger","parameters":[{"name":"webhook_id","in":"path","description":"Webhook ID (non-secret)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTriggerRequest"}}},"required":true},"responses":{"202":{"description":"Agent run created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTriggerResponse"}}}},"401":{"description":"Missing or invalid X-Webhook-Token header"},"404":{"description":"Invalid webhook ID"},"422":{"description":"Agent disabled"}}}},"/ai/conversations":{"get":{"tags":["AI Chat"],"summary":"List every active conversation across all projects, most-recently-active\nfirst, annotated with project name/slug. Powers the unified \"all chats\"\nswitcher in the AI assistant dock.","operationId":"list_all_conversations","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GlobalConversationResponse"}}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]}},"/ai/pricing":{"get":{"tags":["AI Gateway Pricing"],"operationId":"get_pricing","responses":{"200":{"description":"Model pricing information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers":{"get":{"tags":["AI Gateway Admin"],"operationId":"list_provider_keys","responses":{"200":{"description":"List of provider keys","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["AI Gateway Admin"],"operationId":"create_provider_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderKeyRequest"}}},"required":true},"responses":{"201":{"description":"Provider key created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/test":{"post":{"tags":["AI Gateway Admin"],"operationId":"test_provider_key_inline","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyRequest"}}},"required":true},"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/{id}":{"delete":{"tags":["AI Gateway Admin"],"operationId":"delete_provider_key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider key deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AI Gateway Admin"],"operationId":"update_provider_key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderKeyRequest"}}},"required":true},"responses":{"200":{"description":"Provider key updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/{id}/test":{"post":{"tags":["AI Gateway Admin"],"operationId":"test_provider_key_by_id","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Provider key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/by-provider":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_by_provider","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Usage broken down by provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderUsage"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/conversations":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_conversations","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 50, max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"user_id","in":"query","description":"Filter by user ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"tags","in":"query","description":"Filter by tags (comma-separated)","required":false,"schema":{"type":"string"}},{"name":"model","in":"query","description":"Filter by model name","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Conversation summaries","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationSummary"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/conversations/{conversation_id}":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_conversation_detail","parameters":[{"name":"conversation_id","in":"path","description":"Conversation ID","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Invocations within a conversation","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsageLogEntry"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/recent":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_recent","parameters":[{"name":"limit","in":"query","description":"Page size (defaults to 20, max 50)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Number of results to skip for pagination (defaults to 0)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"provider","in":"query","description":"Filter by provider name","required":false,"schema":{"type":"string"}},{"name":"model","in":"query","description":"Filter by model name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by HTTP status code (exact match)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"cost_gte","in":"query","description":"Cost greater-than-or-equal, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_gt","in":"query","description":"Cost strictly greater-than, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_lte","in":"query","description":"Cost less-than-or-equal, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_lt","in":"query","description":"Cost strictly less-than, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_gte","in":"query","description":"Total tokens greater-than-or-equal","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_gt","in":"query","description":"Total tokens strictly greater-than","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_lte","in":"query","description":"Total tokens less-than-or-equal","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_lt","in":"query","description":"Total tokens strictly less-than","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Page of recent usage log entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageLogPage"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/summary":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_summary","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Usage summary for the time range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/timeseries":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_timeseries","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"bucket","in":"query","description":"Bucket size: hour, day, week (defaults to day)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Time-series usage data","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TimeseriesBucket"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/top-models":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_top_models","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 10)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Top models by request count","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ModelUsage"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/chat/completions":{"post":{"tags":["AI Gateway"],"operationId":"chat_completions","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}},"required":true},"responses":{"200":{"description":"Chat completion response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"404":{"description":"Model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/embeddings":{"post":{"tags":["AI Gateway"],"operationId":"embeddings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingRequest"}}},"required":true},"responses":{"200":{"description":"Embedding response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"404":{"description":"Model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/models":{"get":{"tags":["AI Gateway"],"operationId":"list_models","responses":{"200":{"description":"List of available models","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/analytics/active-visitors":{"get":{"tags":["Analytics"],"summary":"Get detailed active visitors","operationId":"get_analytics_active_visitors","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"window_minutes","in":"query","description":"Time window in minutes for active visitors (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved active visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveVisitorsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-detail":{"get":{"tags":["Analytics"],"summary":"Get detailed analytics for a specific event","operationId":"get_event_detail","parameters":[{"name":"event_name","in":"query","description":"Event name to get details for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval: hour, day, week, month (default: auto)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventDetailResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-entries":{"get":{"tags":["Analytics"],"summary":"Get paginated list of raw occurrences of a specific event, including custom JSON properties","operationId":"get_event_entries","parameters":[{"name":"event_name","in":"query","description":"Event name to list occurrences for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved event entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventEntriesResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-visitors":{"get":{"tags":["Analytics"],"summary":"Get paginated list of visitors who triggered a specific event","operationId":"get_event_visitors","parameters":[{"name":"event_name","in":"query","description":"Event name to list visitors for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved event visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventVisitorsResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/events":{"get":{"tags":["Analytics"],"operationId":"get_analytics_events_count","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of results to return","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"custom_events_only","in":"query","description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"breakdown","in":"query","description":"Breakdown by geography: 'country', 'region', or 'city' (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event counts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventCount"}}}}},"400":{"description":"Invalid date format, missing required parameters, or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/general-stats":{"get":{"tags":["Analytics"],"summary":"Get general statistics across all projects for a time frame","operationId":"get_general_stats","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_ids","in":"query","description":"Optional: Filter by specific project IDs (comma-separated)","required":false,"schema":{"type":"array","items":{"type":"integer","format":"int32"}}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_project_breakdown","in":"query","description":"Whether to include per-project breakdown (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successfully retrieved general statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneralStatsResponse"}}}},"400":{"description":"Invalid date format or parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/has-events":{"get":{"tags":["Analytics"],"operationId":"check_analytics_has_events","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Analytics events existence check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasAnalyticsEventsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/live-visitors":{"get":{"tags":["Analytics"],"summary":"Get list of currently live visitors from visitor table","operationId":"get_live_visitors_list","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"window_minutes","in":"query","description":"Time window in minutes for live visitors (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved live visitors list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveVisitorsListResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-flow":{"get":{"tags":["Analytics"],"summary":"Get page flow analytics: entry pages, exit pages, drop-off points, and page transitions","operationId":"get_page_flow","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max entry/exit pages to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"transitions_limit","in":"query","description":"Max page transitions to return (default: 50, max: 200)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"min_views_for_dropoff","in":"query","description":"Minimum views for drop-off analysis (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved page flow analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageFlowResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-hourly-sessions":{"get":{"tags":["Analytics"],"operationId":"get_page_hourly_sessions","parameters":[{"name":"page_path","in":"query","description":"The page path to get sessions for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval: 'hour', 'day', 'week', or 'month' (default: auto-determined based on range)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved page sessions with time buckets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageHourlySessionsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-path-detail":{"get":{"tags":["Analytics"],"summary":"Get detailed analytics for a specific page path\nReturns visitors, page views, activity over time, geographic distribution, and referrers","operationId":"get_page_path_detail","parameters":[{"name":"page_path","in":"query","description":"The page path to get details for (URL-encoded)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto based on date range)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved page path detail analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathDetailResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-path-visitors":{"get":{"tags":["Analytics"],"summary":"Get individual visitor sessions for a specific page path","operationId":"get_page_path_visitors","parameters":[{"name":"page_path","in":"query","description":"The page path to get visitors for (URL-encoded)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved page path visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathVisitorsResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-paths":{"get":{"tags":["Analytics"],"operationId":"get_page_paths","parameters":[{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS (optional)","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS (optional)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of page paths to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved page paths","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-paths-sparklines":{"get":{"tags":["Analytics"],"operationId":"get_page_paths_sparklines","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"page_paths","in":"query","description":"Comma-separated list of page paths","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sparkline data for all requested page paths","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathsSparklineResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/recent-activity":{"get":{"tags":["Analytics"],"summary":"Get recent activity events for real-time activity feed","operationId":"get_recent_activity","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"since_id","in":"query","description":"Return events with ID greater than this (cursor-based polling)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","description":"Max events to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved recent activity events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecentActivityResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}":{"get":{"tags":["Analytics"],"summary":"Get detailed information about a specific session including events and request logs","operationId":"get_session_details","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDetails"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}/events":{"get":{"tags":["Analytics"],"operationId":"get_analytics_session_events","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of results to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of results to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionEventsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}/logs":{"get":{"tags":["Analytics"],"operationId":"get_session_logs","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of results to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of results to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionLogsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitor-facets":{"get":{"tags":["Analytics"],"summary":"Get filter dropdown contents for the visitors page. Returns the top\nvalues per dimension with distinct visitor counts so the UI can render\n\"Country — 1,234 visitors\" rows. Each dimension is computed against the\nsegment minus its own filter, so a selected value never collapses its\nown dropdown.","operationId":"get_visitor_facets","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_crawlers","in":"query","description":"Include crawlers (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"has_activity_only","in":"query","description":"Hide ghost visitors (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"per_facet_limit","in":"query","description":"Top N values per dimension (default: 50, max: 200)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"filter_country","in":"query","description":"Geolocation country","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Geolocation region","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Geolocation city","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"First-touch channel","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"First-touch referrer hostname (use 'Direct' for null)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Top values per dimension","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorFacets"}}}},"400":{"description":"Invalid date format or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors":{"get":{"tags":["Analytics"],"summary":"Get list of visitors with summary information","operationId":"get_visitors","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_crawlers","in":"query","description":"Include crawlers (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"limit","in":"query","description":"Maximum number of visitors to return (default: 50)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of visitors to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"has_activity_only","in":"query","description":"Filter to only include visitors with recorded activity (events/sessions). When true, excludes ghost visitors (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"filter_country","in":"query","description":"Geolocation country","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Geolocation region","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Geolocation city","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"First-touch channel","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"First-touch referrer hostname (use 'Direct' for null)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorsResponse"}}}},"400":{"description":"Invalid date format, missing required parameters, or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/guid/{visitor_id}":{"get":{"tags":["Analytics"],"summary":"Get visitor by GUID with geolocation data","operationId":"get_visitor_by_guid","parameters":[{"name":"visitor_id","in":"path","description":"Visitor GUID (supports enc_ prefix for encrypted IDs)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor with geolocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorWithGeolocation"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/id/{id}":{"get":{"tags":["Analytics"],"summary":"Get visitor by numeric ID with geolocation data","operationId":"get_visitor_by_id","parameters":[{"name":"id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor with geolocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorWithGeolocation"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}":{"get":{"tags":["Analytics"],"summary":"Get detailed information about a specific visitor by numeric ID","operationId":"get_visitor_details","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorDetails"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/enrich":{"put":{"tags":["Analytics"],"operationId":"enrich_visitor","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID - can be numeric ID, GUID, or encrypted GUID (enc_xxx)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichVisitorRequest"}}},"required":true},"responses":{"200":{"description":"Successfully enriched visitor data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichVisitorResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/info":{"get":{"tags":["Analytics"],"summary":"Get visitor record from database","operationId":"get_visitor_info","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorRecord"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/journey":{"get":{"tags":["Analytics"],"summary":"Get the complete visitor journey: all events across all sessions, grouped by session","operationId":"get_visitor_journey","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit_sessions","in":"query","description":"Maximum number of sessions to return (default: 50)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor journey","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorJourneyResponse"}}}},"400":{"description":"Invalid parameters"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/sessions":{"get":{"tags":["Analytics"],"summary":"Get all sessions for a specific visitor by numeric ID","operationId":"get_analytics_visitor_sessions","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of sessions to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor sessions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorSessionsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/stats":{"get":{"tags":["Analytics"],"summary":"Get visitor statistics","operationId":"get_visitor_stats","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorStats"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys":{"get":{"tags":["API Keys"],"operationId":"list_api_keys","parameters":[{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"API keys retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["API Keys"],"operationId":"create_api_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}},"required":true},"responses":{"201":{"description":"API key created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"409":{"description":"Conflict - API key name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/permissions":{"get":{"tags":["API Keys"],"operationId":"get_api_key_permissions","responses":{"200":{"description":"Available permissions and roles retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailablePermissions"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}":{"get":{"tags":["API Keys"],"operationId":"get_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["API Keys"],"operationId":"update_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"API key updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"409":{"description":"Conflict - API key name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["API Keys"],"operationId":"delete_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"API key deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/activate":{"post":{"tags":["API Keys"],"operationId":"activate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key activated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/deactivate":{"post":{"tags":["API Keys"],"operationId":"deactivate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key deactivated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/rotate":{"post":{"tags":["API Keys"],"operationId":"rotate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key rotated successfully; the response contains the new plaintext secret, shown only once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/auth/cli/device/approve":{"post":{"tags":["Authentication"],"operationId":"cli_device_approve","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveRequest"}}},"required":true},"responses":{"200":{"description":"Session approved; CLI can now claim the API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Unknown user_code"},"409":{"description":"Already resolved"},"410":{"description":"Session expired"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/deny":{"post":{"tags":["Authentication"],"operationId":"cli_device_deny","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveRequest"}}},"required":true},"responses":{"200":{"description":"Session denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Unknown user_code"},"409":{"description":"Already resolved"},"410":{"description":"Session expired"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/lookup":{"get":{"tags":["Authentication"],"operationId":"cli_device_lookup","parameters":[{"name":"user_code","in":"query","description":"`user_code` as displayed in the CLI / pasted into the URL.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Device session metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceLookupResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Unknown user_code"},"410":{"description":"Device session expired"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/poll":{"post":{"tags":["Authentication"],"operationId":"cli_device_poll","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDevicePollRequest"}}},"required":true},"responses":{"200":{"description":"Poll result; check `status` field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDevicePollResponse"}}}},"404":{"description":"Unknown device_code"},"500":{"description":"Internal server error"}}}},"/auth/cli/device/start":{"post":{"tags":["Authentication"],"operationId":"cli_device_start","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceStartRequest"}}},"required":true},"responses":{"200":{"description":"Device session created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceStartResponse"}}}},"500":{"description":"Internal server error"}}}},"/auth/cli/logout":{"post":{"tags":["Authentication"],"operationId":"cli_logout","responses":{"204":{"description":"API key revoked"},"401":{"description":"Not authenticated"},"403":{"description":"Endpoint requires API key authentication"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/auth/email-status":{"get":{"tags":["Authentication"],"operationId":"email_status","responses":{"200":{"description":"Email configuration status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailStatusResponse"}}}},"500":{"description":"Internal server error"}}}},"/auth/login":{"post":{"tags":["Authentication"],"operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Login successful, session cookie set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"401":{"description":"Invalid credentials, or the account's role requires MFA enrollment that has not been completed"},"500":{"description":"Internal server error"}}}},"/auth/oidc/callback":{"get":{"tags":["Authentication"],"operationId":"oidc_callback","parameters":[{"name":"code","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"state","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"error","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"error_description","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"302":{"description":"Redirect to app with session cookie or login error"}}}},"/auth/oidc/login/{slug}":{"get":{"tags":["Authentication"],"operationId":"start_oidc_login_by_slug","parameters":[{"name":"slug","in":"path","description":"OIDC provider slug (from /email-status or /auth/oidc/providers)","required":true,"schema":{"type":"string"}},{"name":"return_to","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"302":{"description":"Redirect to IdP authorize URL"},"404":{"description":"Provider not found"},"503":{"description":"OIDC provider unreachable"}}}},"/auth/oidc/providers":{"get":{"tags":["Authentication"],"operationId":"list_public_providers","responses":{"200":{"description":"Enabled OIDC providers for login page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProvidersListResponse"}}}}}}},"/auth/password-reset/request":{"post":{"tags":["Authentication"],"operationId":"request_password_reset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRequest"}}},"required":true},"responses":{"200":{"description":"Reset email sent if account exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"503":{"description":"Email service not configured"}}}},"/auth/password-reset/verify":{"post":{"tags":["Authentication"],"operationId":"reset_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Password reset successful","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Invalid or expired token"},"500":{"description":"Internal server error"}}}},"/auth/verify-email":{"get":{"tags":["Authentication"],"operationId":"verify_email","parameters":[{"name":"token","in":"query","description":"Email verification token","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email verified successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Invalid or expired token"},"500":{"description":"Internal server error"}}}},"/auth/verify-mfa":{"post":{"tags":["Authentication"],"operationId":"verify_mfa_challenge","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerificationRequest"}}},"required":true},"responses":{"204":{"description":"MFA verification successful"},"400":{"description":"Invalid request"},"401":{"description":"Invalid MFA code"},"500":{"description":"Internal server error"}}}},"/backups/alerts":{"get":{"tags":["Backups"],"summary":"List open backup alerts.","description":"Returns all alerts that have not yet been resolved, ordered by `opened_at`\ndescending (newest first). The UI renders these as a banner above the\nBackups page content. Alerts are auto-opened by the watcher and\nauto-resolved when the triggering condition clears.\n\n**Schedule overdue** — the backup scheduler did not enqueue a job within\nthe expected window (1 hour past `next_run`). Usually means the scheduler\ntask is dead or wedged.\n\n**Job stalled** — a `backup_jobs` row has been in `state='pending'` for\nmore than 1 hour. The runner never claimed the job. Usually means the\nrunner task is dead or the runner concurrency cap is too low.","operationId":"list_backup_alerts","responses":{"200":{"description":"List of open backup alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupAlertListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/cleanup":{"post":{"tags":["Backups"],"summary":"Preview or run retention using each selected schedule's configured retention days.","operationId":"cleanup_expired_backups","parameters":[{"name":"dry_run","in":"query","description":"Return the backups selected by retention without deleting anything.","required":false,"schema":{"type":"boolean"}},{"name":"schedule_id","in":"query","description":"Limit cleanup to one backup schedule.","required":false,"schema":{"type":["integer","null"],"format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleanupExpiredBackupsRequest"}}},"required":true},"responses":{"200":{"description":"Retention cleanup completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionCleanupReport"}}}},"400":{"description":"Missing or invalid preview candidate list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule or backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Cleanup preview is stale","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Cleanup could not be started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{id}/run":{"post":{"tags":["Backups"],"summary":"Run a backup for an external service manually.","description":"Enqueues the backup for asynchronous execution via the `BackupRunner`\n(ADR-014). Returns `202 Accepted` immediately: pending parent and child\nrows are inserted, and a `backup_jobs` row is enqueued for the resolved\nengine. Poll `GET /backups/{id}` to observe `pending → running → completed`.","operationId":"run_external_service_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunExternalServiceBackupRequest"}}},"required":true},"responses":{"202":{"description":"Backup enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceBackupResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"External service or S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{service_id}/backups":{"get":{"tags":["Backups"],"summary":"List all backups for a specific external service (DB-only, no S3 scan).","description":"Returns a paginated list of backups that belong to this service.\nCompletes in <100 ms regardless of S3 endpoint latency because it\nnever touches S3.","operationId":"list_external_service_backups","parameters":[{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based). Defaults to 1.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"page_size","in":"query","description":"Items per page. Defaults to 20, max 100.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Paginated list of backups for this service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceBackupListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{service_id}/schedules":{"get":{"tags":["Backups"],"summary":"List the schedules that target a specific external service. Useful for\nthe service detail page (\"which schedules back this DB up?\").","operationId":"list_service_schedules","parameters":[{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Schedules backing up this service","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources":{"get":{"tags":["Backups"],"summary":"List all S3 sources","operationId":"list_s3_sources","responses":{"200":{"description":"List of S3 sources","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/S3SourceResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Create a new S3 source","operationId":"create_s3_source","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateS3SourceRequest"}}},"required":true},"responses":{"201":{"description":"S3 source created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/test":{"post":{"tags":["Backups"],"summary":"Test S3 connectivity against a prospective source configuration (before creating it).\nThe credentials are NOT persisted. Useful for validating the form in the UI.","operationId":"test_s3_connection_preview","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateS3SourceRequest"}}},"required":true},"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3ConnectionTestResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}":{"get":{"tags":["Backups"],"summary":"Get an S3 source by ID","operationId":"get_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 source details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Delete an S3 source","operationId":"delete_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"S3 source deleted"},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Backups"],"summary":"Update an S3 source","operationId":"update_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateS3SourceRequest"}}},"required":true},"responses":{"200":{"description":"S3 source updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/backups":{"get":{"tags":["Backups"],"summary":"List all backups in an S3 source","operationId":"list_source_backups","parameters":[{"name":"include_s3_scan","in":"query","description":"When `true`, scan the S3 bucket for backups not tracked in the\nlocal database (useful after disaster-recovery from another Temps\ninstance). Defaults to `false` — the fast DB-only path.","required":false,"schema":{"type":"boolean"}},{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of all backups in the source","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceBackupIndexResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/run":{"post":{"tags":["Backups"],"summary":"Run a backup immediately for an S3 source.","description":"Enqueues the backup for asynchronous execution via the `BackupRunner`\n(ADR-014). Returns `202 Accepted` immediately: a `backups` row is inserted\nwith `state='pending'` and a `backup_jobs` row is enqueued for the\n`ControlPlaneEngine`. Poll `GET /backups/{id}` to observe\n`pending → running → completed`.","operationId":"run_backup_for_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunBackupRequest"}}},"required":true},"responses":{"202":{"description":"Backup enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/set-default":{"post":{"tags":["Backups"],"summary":"Mark an S3 source as the default. All new backups/schedules/services that do not\nexplicitly reference a source will use the default. Returns the updated source.","operationId":"set_default_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 source marked as default","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/test":{"post":{"tags":["Backups"],"summary":"Test connectivity to an existing S3 source using its stored credentials.","operationId":"test_s3_source_connection","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3ConnectionTestResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedule-runs/{id}/cancel":{"post":{"tags":["Backups"],"summary":"Cancel every non-terminal child backup belonging to a schedule run.","description":"Loops over `state IN ('pending','running')` children and flips each via\nthe same path as the per-backup cancel endpoint. The parent\n`schedule_runs.finished_at` is stamped automatically once no live\nchildren remain. Idempotent: cancelling a run with no live children is\na 200 with `cancelled = 0`.","operationId":"cancel_schedule_run","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Cancel processed (idempotent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedule-runs/{id}/jobs":{"get":{"tags":["Backups"],"summary":"List the individual backup jobs for a single scheduler run.","description":"Returns each child `backups` row joined with its external service name and\nthe most-recent `backup_jobs` engine key. Used by the schedule detail\naccordion to show per-job detail on row expand.\n\n`page_size` defaults to 50 and is capped at 200.","operationId":"list_schedule_run_jobs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Jobs for this scheduler run","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunJobEntry"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules":{"get":{"tags":["Backups"],"summary":"List all backup schedules","operationId":"list_backup_schedules","responses":{"200":{"description":"List of backup schedules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Create a new backup schedule","operationId":"create_backup_schedule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBackupScheduleRequest"}}},"required":true},"responses":{"201":{"description":"Backup schedule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}":{"get":{"tags":["Backups"],"summary":"Get a backup schedule by ID","operationId":"get_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Delete a backup schedule","operationId":"delete_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Backup schedule deleted"},"404":{"description":"Backup schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Backups"],"summary":"Update a backup schedule (partial update).","description":"All request fields are optional; only fields that are present in the\nJSON body are updated. Absent fields leave the corresponding column\nunchanged. If `schedule_expression` is changed, `next_run` is\nrecomputed automatically.","operationId":"update_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBackupScheduleRequest"}}},"required":true},"responses":{"200":{"description":"Schedule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/backups":{"get":{"tags":["Backups"],"summary":"List backups for a schedule","operationId":"list_backups_for_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of backups for the schedule","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupResponse"}}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/disable":{"patch":{"tags":["Backups"],"summary":"Disable a backup schedule","operationId":"disable_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/enable":{"patch":{"tags":["Backups"],"summary":"Enable a backup schedule","operationId":"enable_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/run":{"post":{"tags":["Backups"],"summary":"Immediately fan-out a run for the given schedule (Run Now).","description":"Creates one `schedule_runs` row, one control-plane backup job, and one\nbackup job per supported external service — all in a single transaction.\nReturns `202 Accepted` with a [`ScheduleRunResponse`] containing the new\n`schedule_run_id` and the list of enqueued jobs. Returns `409 Conflict` if\na run for this schedule is already in flight or if the schedule is disabled.","operationId":"run_schedule_now","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Fan-out run enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleRunResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Run already in flight or schedule disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/runs":{"get":{"tags":["Backups"],"summary":"Paginated run history for a backup schedule (one row per scheduler tick).","description":"Returns one [`ScheduleRunSummary`] per scheduler tick, with child backup\ncounts aggregated in a single SQL round-trip. Legacy `backups` rows (pre-\nfan-out) are surfaced as synthetic single-job runs so history does not\ndisappear. Ordered by `started_at DESC` (newest first).\n\nUse `GET /backups/schedule-runs/{run_id}/jobs` to drill into a single run.","operationId":"list_schedule_runs","parameters":[{"name":"page","in":"query","description":"Page number (1-based, defaults to 1, clamped to 1 if < 1).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"page_size","in":"query","description":"Items per page (defaults to 20, clamped to 100 if > 100).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Paginated run history for the schedule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleRunSummaryList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/services":{"get":{"tags":["Backups"],"summary":"List the external services attached to a backup schedule.","operationId":"list_schedule_services","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Services attached to this schedule","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExternalServiceSummary"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Attach one or more external services to a backup schedule. Idempotent —\nservices that are already attached are silently skipped (`ON CONFLICT\nDO NOTHING`). Returns the count of newly inserted rows + the total\nmembership after the operation.","operationId":"attach_schedule_services","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachScheduleServicesRequest"}}},"required":true},"responses":{"200":{"description":"Services attached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachScheduleServicesResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/services/{service_id}":{"delete":{"tags":["Backups"],"summary":"Detach a single external service from a backup schedule. Idempotent —\nreturns `204` whether or not a row was actually removed.","operationId":"detach_schedule_service","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service detached (or was not attached)"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}":{"get":{"tags":["Backups"],"summary":"Get a backup by ID","operationId":"get_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Backup details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Permanently delete one terminal backup from object storage and the database.","operationId":"delete_backup","parameters":[{"name":"id","in":"path","description":"Backup UUID","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Backup deleted"},"400":{"description":"Backup artifact cannot be safely attributed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Backup is running, referenced, or lacks safe artifact identity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Object storage or database error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}/cancel":{"post":{"tags":["Backups"],"summary":"Cancel a single in-flight backup.","description":"Flips the parent `backups` row + its latest `backup_jobs` row to\n`failed` with reason `\"cancelled by user \"`. The in-process\n`CancellationToken` is observed on the next heartbeat tick (≤5s), so the\nengine exits cleanly and rollback reaps the sidecar. Idempotent: cancelling\nan already-terminal backup is a 200 with `cancelled = 0`.","operationId":"cancel_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cancel processed (idempotent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}/children":{"get":{"tags":["Backups"],"summary":"List the external-service child backups that belong to a parent backup.","description":"Each entry in `children` corresponds to one `external_service_backups` row,\njoined with `external_services` so the caller receives the service name and\ntype without a second request.\n\nReturns an empty `{ \"children\": [] }` — **not 404** — when the parent\nbackup exists but has no children (e.g. control-plane backups).\nReturns 404 when the parent backup itself does not exist.","operationId":"list_backup_children","parameters":[{"name":"id","in":"path","description":"Integer row id of the parent backup","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Child backup list (may be empty)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChildBackupListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Parent backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob":{"get":{"tags":["Blob"],"summary":"List blobs","operationId":"blob_list","parameters":[{"name":"limit","in":"query","description":"Maximum number of items to return","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"prefix","in":"query","description":"Prefix to filter by","required":false,"schema":{"type":"string"}},{"name":"cursor","in":"query","description":"Continuation token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of blobs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBlobsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Blob"],"summary":"Upload a blob","operationId":"blob_put","requestBody":{"description":"Binary blob data","content":{"application/octet-stream":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"Blob uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Blob"],"summary":"Delete blobs","operationId":"blob_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blobs deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteBlobResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob/copy":{"post":{"tags":["Blob"],"summary":"Copy a blob to a new location","operationId":"blob_copy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopyBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob copied successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Source blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob/disable":{"delete":{"tags":["Blob Management"],"summary":"Disable Blob service","operationId":"blob_disable","responses":{"200":{"description":"Blob service disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableBlobResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Blob service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/enable":{"post":{"tags":["Blob Management"],"summary":"Enable Blob service","operationId":"blob_enable","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob service enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableBlobResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/status":{"get":{"tags":["Blob Management"],"summary":"Get Blob service status","operationId":"blob_status","responses":{"200":{"description":"Blob service status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/update":{"patch":{"tags":["Blob Management"],"summary":"Update Blob service configuration","operationId":"blob_update","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob service updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBlobResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Blob service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/{project_id}/{path}":{"get":{"tags":["Blob"],"summary":"Download a blob","operationId":"blob_download","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","description":"Blob path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Blob content"},"404":{"description":"Blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"head":{"tags":["Blob"],"summary":"Get blob metadata","operationId":"blob_head","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","description":"Blob path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Blob metadata in headers"},"404":{"description":"Blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/dashboard/projects-analytics":{"get":{"tags":["Events"],"summary":"Get dashboard analytics for multiple projects in a single batch request","description":"Returns unique visitor counts and hourly sparkline data for all requested projects\nusing only 2 SQL queries instead of 2×N per-project queries.","operationId":"get_dashboard_projects_analytics","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date for filtering","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved batch analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardProjectsAnalyticsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/activity-graph":{"get":{"tags":["Deployments"],"summary":"Get deployment activity graph showing daily deployment counts\nSimilar to GitHub's contribution graph","operationId":"get_activity_graph","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"days","in":"query","description":"Number of days to include (default: 365)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved activity graph","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityGraphResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/{deployment_id}/vulnerability-scan":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan_by_deployment","parameters":[{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Scan for the specified deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"No scan found for deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on a deployment.","operationId":"DeploymentMetricsGetRange","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics/enable":{"patch":{"tags":["Metrics"],"summary":"Enable or disable OTLP metric ingestion for a deployment.","description":"When `enabled=true`, seeds the default container alert rules for the\ndeployment via [`temps_monitoring::seed_default_container_rules`] (idempotent).","operationId":"DeploymentMetricsToggle","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleDeploymentMetricsRequest"}}},"required":true},"responses":{"200":{"description":"Metrics toggle applied"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics/latest":{"get":{"tags":["Metrics"],"summary":"Fetch the most-recent metric values for a deployment.","operationId":"DeploymentMetricsGetLatest","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of metric name to latest value","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/dns-providers":{"get":{"tags":["DNS Providers"],"summary":"List all DNS providers","operationId":"list_dns_providers","responses":{"200":{"description":"List of DNS providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DnsProviderResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["DNS Providers"],"summary":"Create a new DNS provider","description":"The provider's credentials will be tested before creation.\nIf the connection test fails, the provider will not be created.","operationId":"create_dns_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDnsProviderRequest"}}},"required":true},"responses":{"201":{"description":"DNS provider created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"400":{"description":"Invalid request or connection test failed"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}":{"get":{"tags":["DNS Providers"],"summary":"Get a DNS provider by ID","operationId":"get_dns_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"DNS provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["DNS Providers"],"summary":"Update a DNS provider","description":"If new credentials are supplied, they are tested before the update is\npersisted (same as creation) -- otherwise a provider's credentials (and,\nfor Pebble, its target URL) could be swapped for something invalid or\nunsafe without ever going through validation.","operationId":"update_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDnsProviderRequest"}}},"required":true},"responses":{"200":{"description":"DNS provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["DNS Providers"],"summary":"Delete a DNS provider","operationId":"delete_dns_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"DNS provider deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/domains":{"get":{"tags":["DNS Providers"],"summary":"List managed domains for a provider","operationId":"list_managed_domains","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of managed domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["DNS Providers"],"summary":"Add a managed domain to a provider","operationId":"add_managed_domain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddManagedDomainApiRequest"}}},"required":true},"responses":{"201":{"description":"Managed domain added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/test":{"post":{"tags":["DNS Providers"],"summary":"Test provider connection","operationId":"test_provider_connection","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionTestResult"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/zones":{"get":{"tags":["DNS Providers"],"summary":"List zones available in a provider","operationId":"list_provider_zones","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of zones","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZoneListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}":{"delete":{"tags":["DNS Providers"],"summary":"Remove a managed domain","operationId":"remove_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Managed domain removed"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["DNS Providers"],"summary":"Update a managed domain's settings (hostname mode, sync opt-in, auto-manage).","operationId":"update_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateManagedDomainApiRequest"}}},"required":true},"responses":{"200":{"description":"Managed domain updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/apply-hostname-mode":{"post":{"tags":["DNS Providers"],"summary":"Apply a hostname mode to a managed domain (persist + optional DNS sync +\nroute reload).","operationId":"apply_hostname_mode","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyHostnameModeRequest"}}},"required":true},"responses":{"200":{"description":"Hostname mode applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostnamePreviewResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions or token lacks zone access"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/hostname-preview":{"get":{"tags":["DNS Providers"],"summary":"Preview the impact of switching a managed domain's hostname mode.","operationId":"preview_hostname_mode","parameters":[{"name":"mode","in":"query","description":"Target mode: standard|flat","required":true,"schema":{"type":"string"}},{"name":"sync","in":"query","description":"Include DNS record changes","required":false,"schema":{"type":"boolean"}},{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Hostname mode preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostnamePreviewResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/verify":{"post":{"tags":["DNS Providers"],"summary":"Verify a managed domain","operationId":"verify_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Domain verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns/lookup":{"get":{"tags":["DNS"],"summary":"Lookup DNS A records for a domain","operationId":"lookup_dns_a_records","parameters":[{"name":"domain","in":"query","description":"Domain name to lookup","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved DNS A records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupResponse"}}}},"400":{"description":"Invalid domain name or lookup failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupError"}}}}}}},"/domains":{"get":{"tags":["Domains"],"summary":"List all domains","operationId":"list_domains","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"search","in":"query","description":"Search domains by name (substring match)","required":false,"schema":{"type":["string","null"]},"example":"example.com"}],"responses":{"200":{"description":"Domains retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDomainsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Domains"],"summary":"Create a new domain","description":"Creates a new domain and automatically requests a Let's Encrypt challenge.\nYou can specify the challenge type (HTTP-01 or DNS-01) in the request.\n\n- **HTTP-01**: Validates domain ownership by placing a file on your web server at `/.well-known/acme-challenge/`\n- **DNS-01**: Validates domain ownership by adding a TXT record to your DNS (required for wildcard domains)","operationId":"create_domain","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/by-host/{hostname}":{"get":{"tags":["Domains"],"summary":"Get domain details by hostname","operationId":"get_domain_by_host","parameters":[{"name":"hostname","in":"path","description":"Domain hostname","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Domain details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/by-host/{hostname}/cert-status":{"get":{"tags":["Domains"],"summary":"Get on-demand TLS certificate status for a hostname","description":"Returns the current cert lifecycle state for a single hostname (from the\n`domains` row) plus the most recent on-demand issuance attempt (from the\n`on_demand_cert_attempts` audit log). This is the operator's first-line\ndiagnostic, surfaced by `temps domain cert-status` (ADR-018 §5). Returns the\nhostname with `None` fields when no on-demand activity exists for it (never a\n404, so the CLI can render \"no attempts recorded\").","operationId":"get_on_demand_cert_status","parameters":[{"name":"hostname","in":"path","description":"Domain hostname","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"On-demand cert status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/on-demand-certs":{"get":{"tags":["Domains"],"summary":"List on-demand TLS certificate attempts","description":"Returns rows from the append-only `on_demand_cert_attempts` audit log\n(ADR-018 §5), newest first, each joined with the current authoritative cert\nstate (`status`, `expiration_time`, `backoff_until`) from the `domains` row.\nThis backs the console \"Certificates\" surface. No certificate or private-key\nmaterial is returned — only audit metadata.","operationId":"list_on_demand_certs","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20}],"responses":{"200":{"description":"On-demand cert attempts retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOnDemandCertsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/order":{"get":{"tags":["Domains"],"summary":"Get ACME order for a domain","operationId":"get_domain_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcmeOrderResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Order not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Domains"],"summary":"Create or recreate ACME order for a domain","description":"Creates a new ACME order with Let's Encrypt for the specified domain.\nIf an order already exists, you should cancel it first using the cancel-order endpoint.\nReturns the challenge details that need to be fulfilled (DNS record or HTTP token).","operationId":"create_or_recreate_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainChallengeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Domains"],"summary":"Cancel ACME order for a domain","description":"Cancels the current ACME order for a domain and clears all challenge data.\nThis allows you to start over with a new order if the previous one failed or got stuck.","operationId":"cancel_domain_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order cancelled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/order/finalize":{"post":{"tags":["Domains"],"summary":"Finalize ACME order for a domain","description":"Finalizes the ACME order by completing the challenge validation and requesting the certificate.\nThis should be called after the challenge has been set up (DNS record added or HTTP token served).","operationId":"finalize_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order finalized successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain or order not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/setup-dns":{"post":{"tags":["Domains"],"summary":"Setup DNS challenge records automatically using a DNS provider","description":"This endpoint automatically creates the required DNS TXT records for ACME DNS-01 challenge\nvalidation using a configured DNS provider. The domain must have an active DNS challenge\npending (created via POST /domains/{id}/order with dns-01 challenge type).\n\nThis is similar to how email domain DNS records are auto-provisioned.","operationId":"setup_dns_challenge","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsChallengeRequest"}}},"required":true},"responses":{"200":{"description":"DNS records created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsChallengeResponse"}}}},"400":{"description":"Bad request - DNS provider not configured or no challenge pending"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain or DNS provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}":{"get":{"tags":["Domains"],"summary":"Get domain by ID","operationId":"get_domain_by_id","parameters":[{"name":"domain","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Domains"],"summary":"Delete a domain","operationId":"delete_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Domain deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/challenge-token":{"get":{"tags":["Domains"],"summary":"Get challenge token for a domain (returns plain text token)","operationId":"get_challenge_token","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Challenge token retrieved successfully","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Challenge not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/http-challenge-debug":{"get":{"tags":["Domains"],"summary":"Get HTTP challenge debug information","description":"Returns detailed debug information for HTTP-01 challenge including:\n- Whether a challenge exists for the domain\n- The challenge token and URL that Let's Encrypt will access\n- DNS resolution information showing where the domain currently points\n\nThis is useful for debugging why HTTP-01 challenges fail.","operationId":"get_http_challenge_debug","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Debug information retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpChallengeDebugResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/provision":{"post":{"tags":["Domains"],"summary":"Provision a domain certificate","operationId":"provision_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Certificate provisioning initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/renew":{"post":{"tags":["Domains"],"summary":"Renew domain certificate","description":"For HTTP-01 domains: Automatically renews the certificate\nFor DNS-01 domains (wildcards): Creates a new ACME order and returns challenge data","operationId":"renew_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Certificate renewal initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionResponse"}}}},"202":{"description":"DNS challenge created - manual action required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainChallengeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/status":{"get":{"tags":["Domains"],"summary":"Check domain status","operationId":"check_domain_status","parameters":[{"name":"domain","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains":{"get":{"tags":["Email Domains"],"summary":"List all email domains","operationId":"list_email_domains","parameters":[{"name":"provider_id","in":"query","description":"Only return domains belonging to this provider","required":false,"schema":{"type":["integer","null"],"format":"int32"}}],"responses":{"200":{"description":"List of email domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailDomainResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Email Domains"],"summary":"Create a new email domain","operationId":"create_email_domain","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/by-domain/{domain}":{"get":{"tags":["Email Domains"],"summary":"Get an email domain by domain name with DNS records","operationId":"get_domain_by_name","parameters":[{"name":"domain","in":"path","description":"Domain name (e.g., 'mail.example.com')","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email domain details with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}":{"get":{"tags":["Email Domains"],"summary":"Get an email domain by ID with DNS records","operationId":"get_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email domain details with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Email Domains"],"summary":"Delete an email domain","operationId":"delete_email_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Domain deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/dns-records":{"get":{"tags":["Email Domains"],"summary":"Get DNS records for an email domain","operationId":"get_domain_dns_records","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"DNS records for the domain","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/setup-dns":{"post":{"tags":["Email Domains"],"summary":"Setup DNS records for an email domain using a configured DNS provider","operationId":"setup_dns","parameters":[{"name":"id","in":"path","description":"Email Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsRequest"}}},"required":true},"responses":{"200":{"description":"DNS records setup result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsResponse"}}}},"400":{"description":"Invalid request or DNS provider not configured"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/verify":{"post":{"tags":["Email Domains"],"summary":"Verify an email domain's DNS configuration","operationId":"verify_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain verification result with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers":{"get":{"tags":["Email Providers"],"summary":"List all email providers","operationId":"list_email_providers","responses":{"200":{"description":"List of email providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailProviderResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Email Providers"],"summary":"Create a new email provider","operationId":"create_email_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailProviderRequest"}}},"required":true},"responses":{"201":{"description":"Provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}":{"get":{"tags":["Email Providers"],"summary":"Get an email provider by ID","operationId":"get_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Email Providers"],"summary":"Delete an email provider","operationId":"delete_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Email Providers"],"summary":"Update an email provider","description":"Partial update — any field left out keeps its current value. Most importantly,\nomitting the credential block (`ses_credentials`/`scaleway_credentials`/`smtp_credentials`)\npreserves the stored secret, so operators can rename a provider without re-typing\npasswords. `provider_type` is immutable; to switch providers, delete and recreate.","operationId":"update_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailProviderRequest"}}},"required":true},"responses":{"200":{"description":"Provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"409":{"description":"Provider type mismatch"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/test":{"post":{"tags":["Email Providers"],"summary":"Test an email provider by sending a test email to the logged-in user","operationId":"test_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEmailRequest"}}},"required":true},"responses":{"200":{"description":"Test email result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEmailResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/tracking/setup":{"post":{"tags":["Email Providers"],"summary":"One-click AWS-side setup of SES event tracking (SNS topic + webhook\nsubscription + SESv2 event destination), using the provider's stored\ncredentials.","operationId":"setup_email_tracking","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Setup completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingSetupResponse"}}}},"400":{"description":"Provider does not support event tracking"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"502":{"description":"An AWS call failed — the response detail names the failed step"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/tracking/status":{"get":{"tags":["Email Providers"],"summary":"Live status of SES event tracking for a provider","operationId":"get_email_tracking_status","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Event tracking status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/emails":{"get":{"tags":["Emails"],"summary":"List emails with optional filtering","operationId":"list_emails","parameters":[{"name":"domain_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"project_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"status","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"from_address","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"page","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"List of emails","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEmailsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Emails"],"summary":"Send an email","operationId":"send_email","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailRequestBody"}}},"required":true},"responses":{"201":{"description":"Email sent successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailResponseBody"}}}},"400":{"description":"Invalid request or domain not verified"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/events":{"get":{"tags":["Email Tracking"],"summary":"GET /emails/events","operationId":"get_global_events","parameters":[{"name":"event_type","in":"query","description":"Filter by event type (open, click)","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated tracking events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEventsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/emails/events/stats":{"get":{"tags":["Email Tracking"],"summary":"GET /emails/events/stats","operationId":"get_global_event_stats","responses":{"200":{"description":"Global tracking statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalEventStatsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/emails/stats":{"get":{"tags":["Emails"],"summary":"Get email statistics","operationId":"get_email_stats","parameters":[{"name":"domain_id","in":"query","description":"Optional domain ID to filter stats","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailStatsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/validate":{"post":{"tags":["Email Validation"],"summary":"Validate an email address","operationId":"validate_email","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateEmailRequest"}}},"required":true},"responses":{"200":{"description":"Email validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateEmailResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/{email_id}/track/click/{link_index}":{"get":{"tags":["Email Tracking"],"summary":"Track email link click - redirects to original URL","description":"This endpoint replaces original links in tracked emails.\nNo authentication required - it's called when the recipient clicks a link.","operationId":"track_click","parameters":[{"name":"email_id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}},{"name":"link_index","in":"path","description":"Link index","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"302":{"description":"Redirect to original URL"},"404":{"description":"Link not found"}}}},"/emails/{email_id}/track/open":{"get":{"tags":["Email Tracking"],"summary":"Track email open - returns a 1x1 transparent GIF","description":"This endpoint is embedded as an tag in emails.\nNo authentication required - it's called by the email client.","operationId":"track_open","parameters":[{"name":"email_id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"1x1 transparent tracking pixel"},"404":{"description":"Email not found"}}}},"/emails/{id}":{"get":{"tags":["Emails"],"summary":"Get an email by ID","operationId":"get_email","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking":{"get":{"tags":["Email Tracking"],"summary":"Get email tracking summary","operationId":"get_email_tracking","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracking summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking/events":{"get":{"tags":["Email Tracking"],"summary":"Get email tracking events","operationId":"get_email_events","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}},{"name":"event_type","in":"query","description":"Filter by event type (open, click)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracking events","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrackingEventResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking/links":{"get":{"tags":["Email Tracking"],"summary":"Get tracked links for an email","operationId":"get_email_links","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracked links","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrackedLinkResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/external-services":{"get":{"tags":["External Services"],"summary":"Get all external services","operationId":"list_services","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of external services","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["External Services"],"summary":"Create new external service","operationId":"create_service","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateExternalServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}}}},"/external-services/available-containers":{"get":{"tags":["External Services"],"summary":"List available Docker containers that can be imported as services","operationId":"list_available_containers","responses":{"200":{"description":"List of available containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AvailableContainerInfo"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/by-slug/{slug}":{"get":{"tags":["External Services"],"summary":"Get external service details by slug","operationId":"get_service_by_slug","parameters":[{"name":"slug","in":"path","description":"External service slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"External service details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceDetails"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/health-status-batch":{"get":{"tags":["External Services"],"summary":"Current health status for many services at once","description":"Powers the status dot on the Storage list page. Pass a comma-separated\nlist of service IDs via `?ids=1,2,3`. Omit to get every service.","operationId":"list_service_health_statuses","parameters":[{"name":"ids","in":"query","description":"Comma-separated service IDs. Omit for all services.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Batch of current health statuses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthStatusBatchResponse"}}}},"500":{"description":"Internal server error"}}}},"/external-services/import":{"post":{"tags":["External Services"],"summary":"Import an existing Docker container as a managed external service","operationId":"import_external_service","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportExternalServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service imported successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/projects/{project_id}":{"get":{"tags":["External Services"],"summary":"List services linked to a project","operationId":"list_project_services","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of services linked to project","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/external-services/projects/{project_id}/environment":{"get":{"tags":["External Services"],"summary":"Get all environment variables for all services linked to a project","operationId":"get_project_service_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of service IDs to their environment variables","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"propertyNames":{"type":"integer","format":"int32"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/external-services/providers/metadata":{"get":{"tags":["External Services"],"summary":"Get provider metadata (display names, icons, descriptions)","operationId":"get_providers_metadata","responses":{"200":{"description":"List of provider metadata","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderMetadata"}}}}},"500":{"description":"Internal server error"}}}},"/external-services/providers/metadata/{service_type}":{"get":{"tags":["External Services"],"summary":"Get metadata for a specific provider","operationId":"get_provider_metadata","parameters":[{"name":"service_type","in":"path","description":"Service type (mongodb, postgres, redis, s3)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Provider metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderMetadata"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}}}},"/external-services/types":{"get":{"tags":["External Services"],"summary":"Get available service types","operationId":"get_service_types","responses":{"200":{"description":"List of available service types","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceTypeRoute"}}}}},"500":{"description":"Internal server error"}}}},"/external-services/types/{service_type}/parameters":{"get":{"tags":["External Services"],"summary":"Get parameter schema for a specific service type","operationId":"get_service_type_parameters","parameters":[{"name":"service_type","in":"path","description":"Service type","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Service type parameter schema"},"404":{"description":"Service type not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}":{"get":{"tags":["External Services"],"summary":"Get external service details","operationId":"get_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"External service details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceDetails"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["External Services"],"summary":"Update external service","operationId":"update_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateExternalServiceRequest"}}},"required":true},"responses":{"200":{"description":"Service updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"404":{"description":"Service not found"},"409":{"description":"A major upgrade is in progress for this service"},"500":{"description":"Internal server error"}}},"delete":{"tags":["External Services"],"summary":"Delete external service","operationId":"delete_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service deleted successfully"},"400":{"description":"Cannot delete: service is still linked to projects"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/cluster-health":{"get":{"tags":["External Services"],"summary":"Per-member health for a Postgres HA cluster.","description":"Reads pg_auto_failover's `pgautofailover.node` table from the cluster's\nmonitor (TLS, autoctl_node) and joins each member with its\n`pg_stat_replication` row from the current primary. Returns one row per\ndata member with role/state, sync state, and replay lag.\n\nReturns `200` with `monitor_error` set when the monitor is briefly\nunreachable (UI surfaces it as a banner above the table); the table\nitself is empty in that case. Returns `400` for non-cluster services.","operationId":"get_cluster_health","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Per-member cluster health report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterHealthReportResponse"}}}},"400":{"description":"Service is not a cluster"},"401":{"description":"Unauthorized"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/health-check":{"post":{"tags":["External Services"],"summary":"Run a health check for one service right now","description":"Triggers the same engine-specific probe as the background monitor, writes\na history row, updates the denormalized fields on `external_services`, and\nfires alerts on the Nth consecutive failure (so consecutive-failure state\nstays honest). Returns the fresh snapshot the UI can display immediately.","operationId":"trigger_service_health_check","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Fresh health snapshot after probing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthResponse"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"},"503":{"description":"Health monitor not running on this node"}}}},"/external-services/{id}/health-status":{"get":{"tags":["External Services"],"summary":"Persisted health status for an external service","description":"Returns the latest health probe result recorded by\n`ExternalServiceHealthMonitor`, plus recent check history for sparklines\nand a 24-hour uptime percentage. Safe to poll from the UI every 30s.","operationId":"get_service_health_status","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Max number of recent checks (default 50, max 200)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Current health + recent history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthResponse"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/members":{"post":{"tags":["External Services"],"summary":"Begin adding a single new member to a running cluster.","description":"Currently only `replica` members can be added at runtime. The\nresponse is **202 Accepted** as soon as the validation passes and\nthe placeholder `service_members` row is inserted. The actual\ncontainer provisioning + DNS registration runs in the background;\npoll `GET /external-services/{id}/members/{member_id}` to watch\n`provisioning_step` advance through the phases.","operationId":"add_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddClusterMemberRequest"}}},"required":true},"responses":{"202":{"description":"Cluster member provisioning started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceMemberInfo"}}}},"400":{"description":"Validation failed (wrong topology, status, or role)"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/members/{member_id}":{"get":{"tags":["External Services"],"summary":"Get a single cluster member's current state.","description":"Used by the add-member page to poll the row every second while the\nbackground provisioning task walks through its phases. The\n`provisioning_step` field advances through `inserting_row` →\n`provisioning_container` → `registering_dns` → `done` (or `failed`\nwith `provisioning_error` set).","operationId":"get_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cluster member details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceMemberInfo"}}}},"404":{"description":"Service or member not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["External Services"],"summary":"Remove a single member from a running cluster.","description":"Refuses to remove the monitor (singleton), the current primary\n(failover first), or any member if the cluster would drop below the\n2-data-member quorum required for HA. Stops + removes the container,\ndeletes the row, and drops the Tier-2 DNS record.","operationId":"remove_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Cluster member removed"},"400":{"description":"Validation failed (monitor, primary, or quorum violation)"},"404":{"description":"Service or member not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/members/{member_id}/promote":{"post":{"tags":["External Services"],"summary":"Promote a replica to primary by triggering a pg_auto_failover\nfailover. The monitor demotes the current primary and the chosen\nreplica transitions to primary; the role reconciler then refreshes\nthe role-aliased VIPs (≤30s).","operationId":"promote_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Promotion initiated"},"400":{"description":"Validation failed (monitor, already primary, not running, etc.)"},"404":{"description":"Service or member not found"},"500":{"description":"pg_autoctl perform promotion failed"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on an external service.","description":"Pass `percentile` to compute a histogram quantile instead of a plain\ngauge/counter average.","operationId":"ExternalServiceMetricsGetRange","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/alert-rules":{"get":{"tags":["Metrics"],"summary":"List all monitoring alert rules for an external service.","operationId":"ExternalServiceMetricsGetAlertRules","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of alert rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Metrics"],"summary":"Create a monitoring alert rule for an external service.","description":"If metric collection is enabled and the service engine has default rules,\nseeding is idempotent (ON CONFLICT DO NOTHING).","operationId":"ExternalServiceMetricsCreateAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceCreateAlertRuleRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/alert-rules/{rule_id}":{"put":{"tags":["Metrics"],"summary":"Update an existing monitoring alert rule for an external service.","operationId":"ExternalServiceMetricsUpdateAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUpdateAlertRuleRequest"}}},"required":true},"responses":{"200":{"description":"Updated alert rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Metrics"],"summary":"Delete a monitoring alert rule for an external service.","operationId":"ExternalServiceMetricsDeleteAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/by-database":{"get":{"tags":["Metrics"],"summary":"Return the latest per-database metric values for a Postgres service.","description":"Groups `pg_stat_database` / size metrics by `datname` so the UI can show a\nbreakdown table (each database with its own size, cache-hit ratio, etc.)\nrather than collapsing every database into one value.","operationId":"ExternalServiceMetricsByDatabase","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Per-database metric breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMetricsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/enable":{"patch":{"tags":["Metrics"],"summary":"Enable or disable metric collection for an external service.","description":"When `enabled=true`, seeds the default alert rules for the service's engine\nvia [`temps_monitoring::seed_default_rules`] (idempotent).","operationId":"ExternalServiceMetricsToggle","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleServiceMetricsRequest"}}},"required":true},"responses":{"200":{"description":"Metrics toggle applied"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/latest":{"get":{"tags":["Metrics"],"summary":"Fetch the most-recent value for every tracked metric on an external service.","operationId":"ExternalServiceMetricsGetLatest","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of metric name to latest value","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/status":{"get":{"tags":["Metrics"],"summary":"Return the freshness status (last-received timestamp) for a service.","description":"Cheap O(1) lookup against `service_metrics_status` — used by the UI to show\n\"last received at …\" without scanning the metrics hypertable.","operationId":"ExternalServiceMetricsStatus","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Metrics freshness status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsStatusResponse"}}}},"503":{"description":"Metrics not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/parameters/{param_name}":{"get":{"tags":["External Services"],"summary":"Reveal one sensitive service parameter. Service detail responses never\ncontain plaintext values; every successful reveal is recorded separately.","operationId":"reveal_service_parameter","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"param_name","in":"path","description":"Sensitive parameter name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sensitive parameter value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveValueResponse"}}}},"400":{"description":"Parameter is not sensitive"},"403":{"description":"Caller cannot access a project linked to this service"},"404":{"description":"Service or parameter not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/preview-environment-masked":{"get":{"tags":["External Services"],"summary":"Get environment variables preview with masked sensitive values","operationId":"get_service_preview_environment_variables_masked","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Preview of environment variables with sensitive values masked as ***","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/preview-environment-names":{"get":{"tags":["External Services"],"summary":"Get environment variable names preview (safe - no sensitive values)","operationId":"get_service_preview_environment_variable_names","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variable names that would be provided","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects":{"get":{"tags":["External Services"],"summary":"List projects linked to service","operationId":"list_service_projects","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of linked projects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["External Services"],"summary":"Link service to project","operationId":"link_service_to_project","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service linked to project successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}},"404":{"description":"Service or project not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}":{"delete":{"tags":["External Services"],"summary":"Unlink service from project","operationId":"unlink_service_from_project","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service unlinked from project successfully"},"404":{"description":"Service link not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}/environment":{"get":{"tags":["External Services"],"summary":"Get all environment variables for a service-project pair","operationId":"get_service_environment_variables","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariableInfo"}}}}},"404":{"description":"Service or project not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}/environment/{var_name}":{"get":{"tags":["External Services"],"summary":"Get specific environment variable for a service-project pair","operationId":"get_service_environment_variable","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_name","in":"path","description":"Environment variable name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableInfo"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Service, project, or variable not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/resources":{"patch":{"tags":["External Services"],"summary":"Update a service's resource limits (memory, CPU caps).","description":"Persists the new caps to the encrypted config AND live-applies them\nvia Docker's update API. Memory and CPU can be hot-changed without a\nrestart on running containers; stopped containers also accept the\nupdate and pick up the new caps on next start.\n\nPass `null` (or omit) any field to leave it unlimited. A request where\nevery field is `null` removes any existing limits.\n\nThe response includes a per-container `applied[]` list so the caller\ncan tell which members got the update and which were skipped (e.g.,\ncontainer not yet created, or `docker update` rejected because the\nnew memory cap is below current usage).","operationId":"update_service_resources","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResourceLimits"}}},"required":true},"responses":{"200":{"description":"Updated resource limits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceLimitsUpdateResponse"}}}},"400":{"description":"Invalid resource limits"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/restore":{"post":{"tags":["Restore"],"operationId":"start_restore","parameters":[{"name":"id","in":"path","description":"External service id (source for the restore)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRestoreRequest"}}},"required":true},"responses":{"202":{"description":"Restore run started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreRunView"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup or service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-capabilities":{"get":{"tags":["Restore"],"operationId":"get_restore_capabilities","parameters":[{"name":"id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Capabilities declared by the service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreCapabilitiesResponse"}}}},"404":{"description":"Service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-plan":{"post":{"tags":["Restore"],"operationId":"plan_restore","parameters":[{"name":"id","in":"path","description":"Target service id","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRestoreRequest"}}},"required":true},"responses":{"200":{"description":"Preview of what the restore will do","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestorePlan"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup or service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-runs":{"get":{"tags":["Restore"],"operationId":"list_restore_runs_for_service","parameters":[{"name":"id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Recent restore runs for the service","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RestoreRunView"}}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/retry":{"post":{"tags":["External Services"],"summary":"Retry a failed cluster service initialization.","description":"Cleans up any leftover containers from the previous attempt and\nre-runs cluster initialization with the provided member specifications.","operationId":"retry_cluster","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryClusterRequest"}}},"required":true},"responses":{"200":{"description":"Cluster retry initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Service is not a failed cluster"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/runtime":{"get":{"tags":["External Services"],"summary":"Inspect a service's container(s): status, restart count, OOM-killed flag,\nexit code, and the cgroup limits actually applied.","operationId":"get_service_runtime","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container runtime snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceRuntimeReport"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/start":{"post":{"tags":["External Services"],"summary":"Start an external service","operationId":"start_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Service started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"404":{"description":"Service not found"},"409":{"description":"A Postgres major upgrade is in progress for this service"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/stats":{"get":{"tags":["External Services"],"summary":"Sample current CPU/memory usage from each of a service's containers.\nOne-shot sample, no streaming. Cheap to call (single Docker round-trip\nper member) so the UI can poll on a 5–10s interval.","operationId":"get_service_stats","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container stats snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceStatsReport"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/stop":{"post":{"tags":["External Services"],"summary":"Stop an external service","operationId":"stop_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Service stopped successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/upgrade":{"post":{"tags":["External Services"],"summary":"Upgrade external service to new Docker image with data migration\nThis endpoint uses service-specific upgrade procedures (e.g., pg_upgrade for PostgreSQL)","operationId":"upgrade_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeExternalServiceRequest"}}},"required":true},"responses":{"200":{"description":"Service upgraded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request or upgrade not supported"},"404":{"description":"Service not found"},"409":{"description":"A major upgrade is already in progress for this service"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/wal-health":{"get":{"tags":["External Services"],"summary":"Postgres WAL & archive health snapshot","description":"Returns the latest WAL/archive health snapshot recorded by the background\nhealth monitor for a Postgres external service. Powers the warning banner\non the service detail page when the disk is filling up due to stale\nreplication slots, archive backlog, or misconfigured `archive_command`.\n\nReturns 404 when no snapshot exists yet (probe hasn't run, or the service\nisn't Postgres).","operationId":"getPostgresWalHealth","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest WAL health snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostgresWalHealth"}}}},"404":{"description":"Service not found, or no WAL snapshot available"},"500":{"description":"Internal server error"}}}},"/external-services/{service_id}/pg-stat-statements/enable":{"post":{"tags":["External Services"],"summary":"Enable `pg_stat_statements` on a standalone Postgres service.","description":"Stops the container and restarts it so that the\n`shared_preload_libraries=pg_stat_statements` CMD flag (baked into every\nnew standalone Postgres container) takes effect. The named data volume is\nreused unchanged — no data is lost.\n\n**Clustered (HA) services are rejected** with 422 — a blind single-container\nrestart bypasses controlled failover. For clustered services the response\nbody describes the manual rolling-restart steps.\n\nConfirmation is the caller's responsibility (UI dialog / CLI `--yes` flag)\nbefore invoking this endpoint.","operationId":"ExternalServiceEnablePgStatStatements","parameters":[{"name":"service_id","in":"path","description":"ID of the provisioned standalone Postgres service","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container restarted; pg_stat_statements now active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnablePgStatStatementsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (requires external_services:write)"},"404":{"description":"Service not found"},"422":{"description":"Service is not standalone Postgres (cluster or wrong type)"},"500":{"description":"Restart failed"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/pg-stat-statements/slow-queries":{"get":{"tags":["External Services"],"operationId":"get_slow_queries","parameters":[{"name":"service_id","in":"path","description":"ID of the provisioned Postgres service","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based). Defaults to 1.","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}},{"name":"page_size","in":"query","description":"Number of rows per page (1–100). Defaults to 20.","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}},{"name":"sort_by","in":"query","description":"Column to sort by: one of `calls`, `total_exec_time_ms`,\n`mean_exec_time_ms`, `rows`, `cache_hit_ratio`. Defaults to\n`mean_exec_time_ms`. Applied server-side so ordering stays\nconsistent across pages.","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","description":"Sort direction: `asc` or `desc`. Defaults to `desc`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Paginated slow queries from pg_stat_statements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlowQueriesResponse"}}}},"400":{"description":"Invalid pagination or sort parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (requires external_services:read)"},"404":{"description":"Service not found"},"422":{"description":"Service is not a Postgres service"},"503":{"description":"pg_stat_statements extension not available (container restart required)"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers":{"get":{"tags":["External Services - Query"],"summary":"List containers at the root level (databases, keyspaces, etc.)","operationId":"list_root_containers","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of root containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}":{"get":{"tags":["External Services - Query"],"summary":"List containers at a specific path\nPath segments are separated by forward slashes\nExample: /external-services/1/query/containers/mydb lists schemas in database \"mydb\"","operationId":"list_containers_at_path","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities":{"get":{"tags":["External Services - Query"],"summary":"List entities (tables, collections, etc.) in a container\nExample: /external-services/1/query/containers/mydb/public/entities lists tables in the public schema","operationId":"list_entities","parameters":[{"name":"limit","in":"query","description":"Maximum number of entities to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","minimum":0}},{"name":"token","in":"query","description":"Continuation token for pagination","required":false,"schema":{"type":"string"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of entities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEntitiesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}":{"get":{"tags":["External Services - Query"],"summary":"Get detailed information about an entity (table schema)","operationId":"get_entity_info","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Entity details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityInfoResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service, container, or entity not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}/data":{"post":{"tags":["External Services - Query"],"summary":"Query data from an entity with optional filters, pagination, and sorting","operationId":"query_data","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryDataRequest"}}},"required":true},"responses":{"200":{"description":"Query results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryDataResponse"}}}},"400":{"description":"Invalid query"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service, container, or entity not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}/download":{"get":{"tags":["External Services - Query"],"summary":"Download an object (S3 only) as a streaming response","operationId":"download_object","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Object data stream","content":{"application/octet-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Object not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/info":{"get":{"tags":["External Services - Query"],"summary":"Get information about a specific container","operationId":"get_container_info","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/explorer-support":{"get":{"tags":["External Services - Query"],"summary":"Check if a service supports query explorer functionality","operationId":"check_explorer_support","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Explorer support information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExplorerSupportResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades":{"get":{"tags":["Postgres Upgrades"],"summary":"List recent upgrades for a single service (newest first, page size 50).","operationId":"list_pg_upgrades","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Recent upgrades","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}}},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Postgres Upgrades"],"summary":"Start a new PostgreSQL major-version upgrade for a service.","operationId":"start_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartPgUpgradeRequest"}}},"required":true},"responses":{"201":{"description":"Upgrade started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"400":{"description":"Invalid request"},"409":{"description":"An upgrade is already running for this service"},"412":{"description":"No default S3 source configured"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}":{"get":{"tags":["Postgres Upgrades"],"summary":"Get a single upgrade by id, scoped to a service.","operationId":"get_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Upgrade","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/cancel":{"post":{"tags":["Postgres Upgrades"],"summary":"Cancel an in-flight upgrade. The orchestrator stops at its next phase\nboundary; already-terminal upgrades return 409.","operationId":"cancel_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cancellation requested","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Upgrade already terminal"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/logs":{"get":{"tags":["Postgres Upgrades"],"summary":"Get the accumulated JSONL log content for an upgrade (for dashboard display).","operationId":"get_pg_upgrade_logs","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Log content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeLogResponse"}}}},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/retry":{"post":{"tags":["Postgres Upgrades"],"summary":"Retry a failed upgrade. The phase is preserved, so the state machine\nresumes from where it failed.","operationId":"retry_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Retry scheduled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"400":{"description":"Upgrade is not in a retriable state"},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/rollback":{"post":{"tags":["Postgres Upgrades"],"summary":"Roll a completed upgrade back to its pre-upgrade PGDATA volume and old image.\nOnly valid while the rollback retention window is still open (see\n`ROLLBACK_RETENTION_DAYS`) and the rollback volume has not been swept.","operationId":"rollback_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Rollback complete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Upgrade is not in a rollbackable state (not completed, volume swept, or retention expired)"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/files/{file_path}":{"get":{"tags":["Files"],"operationId":"get_file","parameters":[{"name":"file_path","in":"path","description":"Relative path to the file from static directory","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File content retrieved successfully","content":{"application/octet-stream":{}}},"401":{"description":"Authentication required"},"403":{"description":"Access denied - path outside static directory or insufficient permissions"},"404":{"description":"File not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/flags/snapshot":{"get":{"tags":["Feature Flags"],"summary":"Every flag for the caller's environment, collapsed to what the evaluator\nneeds.","description":"Scope comes from the deployment token, never from the URL: a container's\nbaked-in `TEMPS_API_TOKEN` identifies exactly one project (and usually one\nenvironment), so a compromised app cannot read another tenant's flags by\nchanging a path parameter.\n\nSupports `If-None-Match`, so the SDK's background poll is a 304 in the\ncommon case.","operationId":"get_flag_snapshot","parameters":[{"name":"environment_id","in":"query","description":"Required only when the calling token is project-wide rather than scoped\nto a single environment.","required":false,"schema":{"type":["integer","null"],"format":"int32"}}],"responses":{"200":{"description":"Snapshot for the environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagSnapshotResponse"}}}},"304":{"description":"Snapshot unchanged"},"400":{"description":"Environment could not be determined"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/geo/{ip}":{"get":{"tags":["geo"],"summary":"Get geolocation information for an IP address","operationId":"get_ip_geolocation","parameters":[{"name":"ip","in":"path","description":"IP address to geolocate (IPv4 or IPv6)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Geolocation information retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeoLocationResponse"}}}},"400":{"description":"Invalid IP address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP address not found in database","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/git-connections":{"get":{"tags":["Git Providers"],"summary":"List user's git provider connections","operationId":"list_connections","parameters":[{"name":"page","in":"query","description":"Page number for pagination (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (default: 30, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (created_at, updated_at, account_name)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc), default: desc","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of connections","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}":{"delete":{"tags":["Git Providers"],"summary":"Permanently delete a git provider connection","operationId":"delete_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Connection deleted successfully"},"400":{"description":"Connection is in use by projects and cannot be deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/activate":{"post":{"tags":["Git Providers"],"summary":"Activate a git provider connection","operationId":"activate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection activated successfully"},"400":{"description":"Provider is deactivated and connection cannot be activated"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/deactivate":{"post":{"tags":["Git Providers"],"summary":"Deactivate a git provider connection","operationId":"deactivate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection deactivated successfully"},"400":{"description":"Connection is in use by projects and cannot be deactivated"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/health-check":{"post":{"tags":["Git Provider Connections"],"summary":"Run an on-demand health check for a git connection.","description":"Probes the upstream (GitHub App, PAT, or OAuth token), persists the result,\nand fires admin notifications on status transitions. Returns the updated\nconnection.","operationId":"run_connection_health_check","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Health check completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/repositories":{"get":{"tags":["Git Providers"],"summary":"List repositories for a specific connection","description":"Fetches repositories from the connected git provider with support for pagination, search, and filtering.\nThis endpoint calls the provider's API directly to get the most up-to-date repository list.","operationId":"list_repositories_by_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, etc.)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/sync":{"post":{"tags":["Git Providers"],"summary":"Start a repository sync for a connection","description":"Kicks off a background sync of the connection's repositories from the\nprovider. Returns `202 Accepted` immediately — the caller should poll\nthe connection endpoint for `syncing` / `synced_repository_count`\nupdates rather than waiting on this response. The sync is guarded by\na hard deadline and always releases the `syncing` flag on exit, so a\nclient that disconnects mid-sync will not leave the connection stuck.","operationId":"sync_repositories","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Repository sync started in background","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositorySyncStartedResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"409":{"description":"Sync already in progress"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/update-token":{"post":{"tags":["Git Provider Connections"],"summary":"Update access token for a connection (when tokens expire or are rotated)","operationId":"update_connection_token","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTokenResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/validate":{"get":{"tags":["Git Provider Connections"],"summary":"Validate a connection by testing the access token","operationId":"validate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers":{"get":{"tags":["Git Providers"],"summary":"List all git providers","operationId":"list_git_providers","responses":{"200":{"description":"List of providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Git Providers"],"summary":"Create a new git provider configuration","operationId":"create_git_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderRequest"}}},"required":true},"responses":{"201":{"description":"Provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/bitbucket":{"post":{"tags":["Git Providers"],"summary":"Create a Bitbucket Cloud provider with access token or app password authentication","operationId":"create_bitbucket_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBitbucketRequest"}}},"required":true},"responses":{"201":{"description":"Bitbucket provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — missing or invalid auth fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/generic":{"post":{"tags":["Git Providers"],"summary":"Create a Generic git provider for self-hosted or arbitrary HTTPS git hosts.\nSupports public repositories (no token) and private repositories (token-based).","operationId":"create_generic_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGenericRequest"}}},"required":true},"responses":{"201":{"description":"Generic git provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — invalid clone URL or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitea/pat":{"post":{"tags":["Git Providers"],"summary":"Create a Gitea Personal Access Token provider","operationId":"create_gitea_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGiteaPATRequest"}}},"required":true},"responses":{"201":{"description":"Gitea PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — invalid URL or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/github/pat":{"post":{"tags":["Git Providers"],"summary":"Create a GitHub Personal Access Token provider","operationId":"create_github_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitHubPATRequest"}}},"required":true},"responses":{"201":{"description":"GitHub PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitlab/oauth":{"post":{"tags":["Git Providers"],"summary":"Create a GitLab OAuth provider","operationId":"create_gitlab_oauth_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitLabOAuthRequest"}}},"required":true},"responses":{"201":{"description":"GitLab OAuth provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitlab/pat":{"post":{"tags":["Git Providers"],"summary":"Create a GitLab PAT provider","operationId":"create_gitlab_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitLabPATRequest"}}},"required":true},"responses":{"201":{"description":"GitLab PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}":{"get":{"tags":["Git Providers"],"summary":"Get a specific git provider","operationId":"get_git_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Git Providers"],"summary":"Permanently delete a git provider","operationId":"delete_git_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider deleted successfully"},"400":{"description":"Provider has connections and cannot be deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/activate":{"post":{"tags":["Git Providers"],"summary":"Activate a git provider","operationId":"activate_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider activated successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/callback":{"get":{"tags":["Git Providers"],"summary":"Handle OAuth callback for a git provider","operationId":"handle_git_provider_oauth_callback","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"code","in":"query","description":"OAuth authorization code","required":true,"schema":{"type":"string"}},{"name":"state","in":"query","description":"CSRF state token","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to success page"},"400":{"description":"Bad request"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}}}},"/git-providers/{provider_id}/connections":{"get":{"tags":["Git Providers"],"summary":"Get connections for a specific git provider","operationId":"get_provider_connections","parameters":[{"name":"provider_id","in":"path","description":"Provider ID to get connections for","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of connections for the provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConnectionResponse"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/credentials":{"patch":{"tags":["Git Providers"],"summary":"Partially update credentials for an existing git provider. Only the fields\nyou send are replaced; omitted fields keep their stored values. Fields that\ndon't apply to the provider's auth method are ignored on the service side.","operationId":"update_git_provider_credentials","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderCredentialsRequest"}}},"required":true},"responses":{"200":{"description":"Credentials updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/deactivate":{"post":{"tags":["Git Providers"],"summary":"Deactivate a git provider","operationId":"deactivate_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider deactivated successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/deletion-check":{"get":{"tags":["Git Providers"],"summary":"Check if a git provider can be safely deleted","operationId":"check_provider_deletion_safety","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deletion check result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderDeletionCheckResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/oauth/authorize":{"get":{"tags":["Git Providers"],"summary":"Start OAuth flow for a git provider","operationId":"start_git_provider_oauth","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"302":{"description":"Redirect to OAuth provider"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/repositories":{"get":{"tags":["Git Providers"],"summary":"List all repositories for a specific provider","description":"Lists repositories synced to the database across every connection under\nthis provider, with the same pagination/filtering as `/repositories`.","operationId":"list_repositories_by_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, watchers, size, issues)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/safe-delete":{"delete":{"tags":["Git Providers"],"summary":"Safely delete a git provider (only if no projects are using it)","operationId":"delete_provider_safely","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider successfully deleted"},"400":{"description":"Cannot delete provider because it's in use"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git/public/{provider}/{owner}/{repo}":{"get":{"tags":["Public Repositories"],"summary":"Get information about a public repository (supports GitHub and GitLab)","operationId":"get_public_repository","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRepositoryInfo"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/git/public/{provider}/{owner}/{repo}/branches":{"get":{"tags":["Public Repositories"],"summary":"Get branches for a public repository (supports GitHub and GitLab)","operationId":"get_public_branches","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/git/public/{provider}/{owner}/{repo}/presets":{"get":{"tags":["Public Repositories"],"summary":"Detect presets for a public repository (supports GitHub and GitLab)","operationId":"detect_public_presets","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"branch","in":"query","description":"Branch name to detect presets for (default: repository's default branch)","required":false,"schema":{"type":["string","null"]}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Detected presets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPresetResponse"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository or branch not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/imports/discover":{"post":{"tags":["Imports"],"summary":"Discover workloads from a source","operationId":"discover_workloads","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverRequest"}}},"required":true},"responses":{"200":{"description":"List of discovered workloads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/execute":{"post":{"tags":["Imports"],"summary":"Execute an import","operationId":"execute_import","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteImportRequest"}}},"required":true},"responses":{"202":{"description":"Import execution started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteImportResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/plan":{"post":{"tags":["Imports"],"summary":"Create an import plan","operationId":"create_plan","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequest"}}},"required":true},"responses":{"200":{"description":"Import plan created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/sources":{"get":{"tags":["Imports"],"summary":"List available import sources","operationId":"list_sources","responses":{"200":{"description":"List of available import sources","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImportSourceInfo"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/{session_id}":{"get":{"tags":["Imports"],"summary":"Get import status","operationId":"get_import_status","parameters":[{"name":"session_id","in":"path","description":"Import session ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Import status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Import session not found"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}":{"get":{"tags":["Status Page"],"summary":"Get an incident by ID","operationId":"get_incident","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved incident","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}/status":{"patch":{"tags":["Status Page"],"summary":"Update incident status","operationId":"update_incident_status","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIncidentStatusRequest"}}},"required":true},"responses":{"200":{"description":"Incident status updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}/updates":{"get":{"tags":["Status Page"],"summary":"Get incident updates","operationId":"get_incident_updates","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved incident updates","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IncidentUpdateResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes":{"get":{"tags":["Nodes"],"summary":"List all registered nodes (admin — session auth via RequireAuth)","operationId":"admin_list_nodes","responses":{"200":{"description":"List of nodes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/register":{"post":{"tags":["Nodes"],"summary":"Register a new worker node or reconnect an existing one","operationId":"register_node","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeApiRequest"}}},"required":true},"responses":{"200":{"description":"Node reconnected successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeResponse"}}}},"201":{"description":"Node registered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeResponse"}}}},"400":{"description":"Validation error"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}":{"get":{"tags":["Nodes"],"summary":"Get a specific node by ID (admin — session auth via RequireAuth)","operationId":"admin_get_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeInfoResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Nodes"],"summary":"Remove a node from the cluster entirely. The node should be drained first\nto ensure containers have been rescheduled. If the node still has active\ncontainers, it will be drained automatically before removal.","operationId":"admin_remove_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveNodeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"409":{"description":"Node still has active containers"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/containers":{"get":{"tags":["Nodes"],"summary":"List all containers running on a specific node","operationId":"admin_list_node_containers","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Containers on this node","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeContainerListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/dns/ack":{"post":{"tags":["Internal DNS"],"summary":"`POST /internal/nodes/{node_id}/dns/ack`","operationId":"post_dns_ack","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsAckRequest"}}},"required":true},"responses":{"200":{"description":"ACK accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsAckResponse"}}}},"400":{"description":"ACK higher than server generation"},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/dns/changes":{"get":{"tags":["Internal DNS"],"summary":"`GET /internal/nodes/{node_id}/dns/changes?since=N`","operationId":"get_dns_changes","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"since","in":"query","description":"Highest generation the agent has already applied. Pass `0` to\nrequest a full zone snapshot. Defaults to `0` if omitted.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Diff or full snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsChangesResponse"}}}},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/drain":{"get":{"tags":["Nodes"],"summary":"Get the drain status for a node, including migration progress.","description":"Returns container counts and whether the drain is complete.\nCan be polled to track drain progress.","operationId":"admin_drain_status","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Drain status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrainStatusResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Nodes"],"summary":"Drain a node: mark it as \"draining\" so no new replicas are scheduled on it,\nand trigger redeployment of all affected environments so their containers\nare rescheduled to healthy nodes.","operationId":"admin_drain_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node drain initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrainNodeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Nodes"],"summary":"Undrain (reactivate) a node so it can accept new deployments again.\nOnly works for nodes in \"draining\" or \"drained\" status.","operationId":"admin_undrain_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node reactivated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UndrainNodeResponse"}}}},"400":{"description":"Node not in drainable state"},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/heartbeat":{"post":{"tags":["Nodes"],"summary":"Receive a heartbeat from a worker node","operationId":"node_heartbeat","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatApiRequest"}}},"required":true},"responses":{"200":{"description":"Heartbeat received","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/network/peers":{"get":{"tags":["Nodes"],"summary":"`GET /internal/nodes/{node_id}/network/peers`","operationId":"list_peers","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Peer list and self-allocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeerListResponse"}}}},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/s3-credentials/{s3_source_id}":{"get":{"tags":["Nodes"],"summary":"Get decrypted S3 credentials for a backup/restore operation.","description":"Agents call this endpoint to receive the S3 credentials they need to upload\nor download backups. The credentials are decrypted from the stored S3 source\nand returned over the authenticated TLS/WireGuard channel.","operationId":"get_s3_credentials","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"s3_source_id","in":"path","description":"S3 source ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3CredentialsResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"S3 source not found"},"500":{"description":"Internal server error"}}}},"/ip-access-control":{"get":{"tags":["IP Access Control"],"summary":"List all IP access control rules","operationId":"list_ip_access_control","parameters":[{"name":"action","in":"query","description":"Filter by action (\"block\" or \"allow\")","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of IP access control rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["IP Access Control"],"summary":"Create a new IP access control rule","operationId":"create_ip_access_control","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIpAccessControlRequest"}}},"required":true},"responses":{"201":{"description":"IP access control rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate IP address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ip-access-control/check/{ip}":{"get":{"tags":["IP Access Control"],"summary":"Check if an IP address is blocked","operationId":"check_ip_blocked","parameters":[{"name":"ip","in":"path","description":"IP address to check","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"IP block status"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ip-access-control/{id}":{"get":{"tags":["IP Access Control"],"summary":"Get a single IP access control rule by ID","operationId":"get_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"IP access control rule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["IP Access Control"],"summary":"Delete an IP access control rule","operationId":"delete_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"IP access control rule deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["IP Access Control"],"summary":"Update an IP access control rule","operationId":"update_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIpAccessControlRequest"}}},"required":true},"responses":{"200":{"description":"IP access control rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/kv/del":{"post":{"tags":["KV Store"],"summary":"Delete one or more keys","operationId":"kv_del","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DelRequest"}}},"required":true},"responses":{"200":{"description":"Keys deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DelResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/disable":{"delete":{"tags":["KV Management"],"summary":"Disable KV service","operationId":"kv_disable","responses":{"200":{"description":"KV service disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableKvResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"KV service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/enable":{"post":{"tags":["KV Management"],"summary":"Enable KV service","operationId":"kv_enable","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableKvRequest"}}},"required":true},"responses":{"200":{"description":"KV service enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableKvResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/expire":{"post":{"tags":["KV Store"],"summary":"Set expiration on a key","operationId":"kv_expire","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireRequest"}}},"required":true},"responses":{"200":{"description":"Expiration set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/get":{"post":{"tags":["KV Store"],"summary":"Get a value by key","operationId":"kv_get","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetRequest"}}},"required":true},"responses":{"200":{"description":"Value retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/incr":{"post":{"tags":["KV Store"],"summary":"Increment a numeric value","operationId":"kv_incr","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncrRequest"}}},"required":true},"responses":{"200":{"description":"Value incremented","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncrResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/keys":{"post":{"tags":["KV Store"],"summary":"Get keys matching a pattern","operationId":"kv_keys","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysRequest"}}},"required":true},"responses":{"200":{"description":"Keys retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/set":{"post":{"tags":["KV Store"],"summary":"Set a value with optional expiration","operationId":"kv_set","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetRequest"}}},"required":true},"responses":{"200":{"description":"Value set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/status":{"get":{"tags":["KV Management"],"summary":"Get KV service status","operationId":"kv_status","responses":{"200":{"description":"KV service status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KvStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/ttl":{"post":{"tags":["KV Store"],"summary":"Get time-to-live for a key","operationId":"kv_ttl","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TtlRequest"}}},"required":true},"responses":{"200":{"description":"TTL retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TtlResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/update":{"patch":{"tags":["KV Management"],"summary":"Update KV service configuration","operationId":"kv_update","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKvRequest"}}},"required":true},"responses":{"200":{"description":"KV service updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKvResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"KV service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/lb/routes":{"get":{"tags":["Load Balancer"],"operationId":"list_routes","responses":{"200":{"description":"List of routes","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RouteResponse"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["Load Balancer"],"operationId":"create_route","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRouteRequest"}}},"required":true},"responses":{"201":{"description":"Route created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"400":{"description":"Invalid request"}}}},"/lb/routes/{domain}":{"get":{"tags":["Load Balancer"],"operationId":"get_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Route found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"404":{"description":"Route not found"}}},"put":{"tags":["Load Balancer"],"operationId":"update_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRouteRequest"}}},"required":true},"responses":{"200":{"description":"Route updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"404":{"description":"Route not found"}}},"delete":{"tags":["Load Balancer"],"operationId":"delete_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Route deleted successfully"},"404":{"description":"Route not found"}}}},"/logout":{"post":{"tags":["Authentication"],"operationId":"logout","responses":{"200":{"description":"Successfully logged out"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/logs/context":{"get":{"tags":["Logs"],"summary":"Get context lines surrounding a specific log line","operationId":"get_log_context","parameters":[{"name":"chunk_id","in":"query","description":"Chunk ID","required":true,"schema":{"type":"string"}},{"name":"line_offset","in":"query","description":"Line offset within the chunk","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"lines","in":"query","description":"Context lines before and after (default: 25)","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"Context lines","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextLogsResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Chunk not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/logs/search":{"post":{"tags":["Logs"],"summary":"Search logs with structured filters and full text search","operationId":"search_logs","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchLogsRequest"}}},"required":true},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchLogsResponse"}}}},"400":{"description":"Invalid search parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/logs/tail":{"get":{"tags":["Logs"],"summary":"Live tail logs via Server-Sent Events","operationId":"tail_logs","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"string"}},{"name":"service","in":"query","description":"Service name","required":true,"schema":{"type":"string"}},{"name":"env","in":"query","description":"Environment","required":true,"schema":{"type":"string"}},{"name":"levels","in":"query","description":"Optional level filters","required":true,"schema":{"type":"array","items":{"type":"string"}}},{"name":"text","in":"query","description":"Optional text filter","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"SSE stream of log lines"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/monitors-health/projects":{"get":{"tags":["Status Page"],"summary":"Get monitor-based health summaries for multiple projects in a single query","operationId":"get_projects_monitor_health","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Health summaries per project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectsMonitorHealthResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}":{"get":{"tags":["Status Page"],"summary":"Get a monitor by ID","operationId":"get_monitor","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved monitor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Status Page"],"summary":"Delete a monitor","operationId":"delete_monitor","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Monitor deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/bucketed":{"get":{"tags":["Status Page"],"summary":"Get bucketed status data for a monitor using TimescaleDB","operationId":"get_bucketed_status","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"interval","in":"query","description":"Bucket interval: '5min', 'hourly', or 'daily' (default: hourly)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) (default: 24 hours ago)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) (default: now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved bucketed status data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusBucketedResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/current-status":{"get":{"tags":["Status Page"],"summary":"Get current status and uptime metrics for a monitor","operationId":"get_current_monitor_status","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Custom start time (ISO 8601) - overrides timeframe","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Custom end time (ISO 8601)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved current status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrentStatusResponse"}}}},"400":{"description":"Invalid time parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/uptime":{"get":{"tags":["Status Page"],"summary":"Get uptime history for a monitor","operationId":"get_uptime_history","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"days","in":"query","description":"Number of days of history (default: 60) - ignored if start_time/end_time provided","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) - overrides days parameter","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) - defaults to now","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved uptime history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UptimeHistoryResponse"}}}},"400":{"description":"Invalid time parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/nodes/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on a node.","operationId":"NodeMetricsGetRange","parameters":[{"name":"id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/notification-preferences":{"get":{"tags":["Notification Preferences"],"summary":"Get notification preferences","operationId":"get_preferences","responses":{"200":{"description":"Successfully retrieved preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Notification Preferences"],"summary":"Update notification preferences","operationId":"update_preferences","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePreferencesRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Notification Preferences"],"summary":"Delete notification preferences","operationId":"delete_preferences","responses":{"204":{"description":"Successfully deleted preferences"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers":{"get":{"tags":["Notification Providers"],"summary":"List all notification providers","operationId":"list_notification_providers","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Successfully retrieved providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}}},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Notification Providers"],"summary":"Create a new notification provider","operationId":"create_notification_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/cloudflare":{"post":{"tags":["Notification Providers"],"summary":"Create a new Cloudflare Email Sending notification provider","operationId":"create_cloudflare_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCloudflareProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Cloudflare provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/cloudflare/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Cloudflare Email Sending notification provider","operationId":"update_cloudflare_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCloudflareProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Cloudflare provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/email":{"post":{"tags":["Notification Providers"],"summary":"Create a new Email notification provider","operationId":"create_notification_email_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNotificationEmailProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Email provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/email/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update an Email notification provider","operationId":"update_notification_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateNotificationEmailProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Email provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/slack":{"post":{"tags":["Notification Providers"],"summary":"Create a new Slack notification provider","operationId":"create_slack_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSlackProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Slack provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/slack/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Slack notification provider","operationId":"update_slack_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlackProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Slack provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/webhook":{"post":{"tags":["Notification Providers"],"summary":"Create a new Webhook notification provider","description":"Webhook providers send notifications as JSON payloads to any HTTP endpoint.\nYou can configure custom headers for authentication (Bearer tokens, API keys, etc.).\nThe webhook will receive a JSON payload with notification details including:\nid, title, message, type, priority, severity, timestamp, and metadata.","operationId":"create_webhook_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Webhook provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/webhook/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Webhook notification provider","operationId":"update_webhook_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Webhook provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}":{"get":{"tags":["Notification Providers"],"summary":"Get a single notification provider","operationId":"get_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Notification Providers"],"summary":"Update a notification provider","operationId":"update_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid masked provider configuration"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Notification Providers"],"summary":"Delete a notification provider","operationId":"delete_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Successfully deleted provider"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}/config/{field}":{"get":{"tags":["Notification Providers"],"operationId":"reveal_notification_provider_config","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"field","in":"path","description":"Sensitive field, such as password or headers.Authorization","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sensitive provider configuration value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"Provider or field not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}/test":{"post":{"tags":["Notification Providers"],"summary":"Test a notification provider","operationId":"test_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/orders":{"get":{"tags":["Domains"],"summary":"List all ACME orders","operationId":"list_orders","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOrdersResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/otel/alerts":{"get":{"tags":["Alerts"],"summary":"List alert rules for a project (newest first, paginated).","operationId":"list_alerts","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Alert rules for the project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Alerts"],"summary":"Create a new alert rule for a project.","operationId":"create_alert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMetricAlertRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/alerts/preview":{"post":{"tags":["Alerts"],"summary":"Backtest an anomaly detector over a time range without saving a rule.","description":"Replays the metric against the same band the evaluator would use, returning\nthe per-bucket band + which points would have fired. Powers the form's\n\"would this have fired?\" preview and the explorer band overlay. Read-only.","operationId":"preview_alert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnomalyPreviewRequest"}}},"required":true},"responses":{"200":{"description":"Per-bucket band + breach points","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnomalyPreviewResponse"}}}},"400":{"description":"Not an anomaly detector / bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/alerts/{id}":{"get":{"tags":["Alerts"],"summary":"Fetch a single alert rule by id.","operationId":"get_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the lookup)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alert rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Alerts"],"summary":"Delete an alert rule.","operationId":"delete_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the delete)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Alerts"],"summary":"Update an alert rule's fields.","operationId":"update_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the update)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMetricAlertRequest"}}},"required":true},"responses":{"200":{"description":"Alert rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/dashboards":{"get":{"tags":["Dashboards"],"summary":"List dashboards for a project (newest first, paginated).","operationId":"list_dashboards","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Dashboards for the project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Dashboards"],"summary":"Create a new dashboard for a project.","operationId":"create_dashboard","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDashboardRequest"}}},"required":true},"responses":{"201":{"description":"Dashboard created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/dashboards/{id}":{"get":{"tags":["Dashboards"],"summary":"Fetch a single dashboard by id.","operationId":"get_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the lookup)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Dashboard","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Dashboards"],"summary":"Delete a dashboard.","operationId":"delete_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the delete)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Dashboard deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Dashboards"],"summary":"Update a dashboard's name and/or layout.","operationId":"update_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the update)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDashboardRequest"}}},"required":true},"responses":{"200":{"description":"Dashboard updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/genai/traces":{"get":{"tags":["GenAI"],"summary":"Query GenAI trace summaries — traces containing spans with `gen_ai.*` attributes.","description":"`duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`\nspan attributes (e.g. time-to-first-token, token latency) often follow the\nOTel GenAI semantic conventions, which use **seconds** (a fractional\ndouble), not milliseconds — do not read them as ms without converting.","operationId":"query_genai_traces","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"gen_ai_system","in":"query","description":"Filter by AI system (openai, anthropic, etc.)","required":false,"schema":{"type":"string"}},{"name":"gen_ai_model","in":"query","description":"Filter by model (gpt-4, claude-sonnet-4-20250514, etc.)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max traces to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"GenAI trace summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenAiTraceSummariesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/genai/traces/{project_id}/{trace_id}":{"get":{"tags":["GenAI"],"summary":"Get GenAI span details for a specific trace.","description":"`duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`\nspan attributes (e.g. time-to-first-token, token latency) often follow the\nOTel GenAI semantic conventions, which use **seconds** (a fractional\ndouble), not milliseconds — do not read them as ms without converting.","operationId":"get_genai_trace","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"path","description":"Trace ID (hex)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"GenAI trace span details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenAiTraceDetailResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/global/traces/{trace_id}":{"get":{"tags":["Traces"],"summary":"Assemble a unified cross-project span waterfall (Phase 2).","description":"Fans out to every project that holds spans for `trace_id` (up to 20\nprojects, 10,000 total spans). Spans are annotated with\n`project_id`/`project_name` and sorted by `start_time ASC`.\n`truncated: true` signals a hit on either cap; `truncated_projects`\nlists the dropped project IDs. See ADR-027 §4 for the full design.","operationId":"getUnifiedTrace","parameters":[{"name":"trace_id","in":"path","description":"Trace ID (32 lowercase hex characters)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Unified cross-project trace waterfall","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnifiedTrace"}}}},"400":{"description":"trace_id is not 32 lowercase hex characters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions or deployment token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/health/{project_id}":{"get":{"tags":["OTel"],"summary":"Get health summaries for a project.","operationId":"get_health","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Health summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/insights/{project_id}":{"get":{"tags":["Insights"],"summary":"List anomaly insights for a project.","operationId":"list_insights","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"status","in":"query","description":"Filter by status (active, resolved)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max insights to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Insights list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/logs":{"get":{"tags":["Telemetry Logs"],"summary":"Query log records with optional filters.","operationId":"query_logs","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"severity","in":"query","description":"Filter by severity (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Full-text search in log body (ILIKE)","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","description":"Filter by correlated trace ID","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max logs to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Log records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-label-keys":{"get":{"tags":["Telemetry Metrics"],"summary":"List the attribute (label) keys observed on a metric — powers the\nlabel-filter key autocomplete.","operationId":"list_metric_label_keys","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Metric to inspect","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Window start (RFC 3339); defaults to 24h before end","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Window end (RFC 3339); defaults to now","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Distinct label keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricLabelKeysResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-label-values":{"get":{"tags":["Telemetry Metrics"],"summary":"List the distinct values seen for a label key on a metric — powers value\nautocomplete once a key is chosen.","operationId":"list_metric_label_values","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Metric to inspect","required":true,"schema":{"type":"string"}},{"name":"label_key","in":"query","description":"Label key whose values to list (must match [a-zA-Z0-9_.:-])","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Window start (RFC 3339); defaults to 24h before end","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Window end (RFC 3339); defaults to now","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Distinct label values","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricLabelValuesResponse"}}}},"400":{"description":"Invalid label key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-names/{project_id}":{"get":{"tags":["Telemetry Metrics"],"summary":"List distinct metric names for a project.","operationId":"list_metric_names","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of metric names","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricNamesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metrics":{"get":{"tags":["Telemetry Metrics"],"summary":"Query metrics with time bucketing.","operationId":"query_metrics","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Filter by metric name","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"environment","in":"query","description":"Filter by deployment environment","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval (e.g. '1 hour', '5 minutes')","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max buckets to return (default: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"metric_type","in":"query","description":"Filter by metric type (gauge, sum, histogram, exponential_histogram, summary)","required":false,"schema":{"type":"string"}},{"name":"aggregation","in":"query","description":"Per-bucket aggregation: avg (default), sum, min, max, count, rate, p50/p95/p99, quantile:0.95","required":false,"schema":{"type":"string"}},{"name":"label_filters","in":"query","description":"Comma-separated key=value data-point label filters (keys must match [a-zA-Z0-9_.:-])","required":false,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Comma-separated label keys to group series by","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Metrics data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricsResponse"}}}},"400":{"description":"Invalid label key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/pipeline-stats":{"get":{"tags":["OTel"],"summary":"Get OTel pipeline statistics (admin/system view).","operationId":"get_pipeline_stats","responses":{"200":{"description":"Pipeline statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStatsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/quota/{project_id}":{"get":{"tags":["OTel"],"summary":"Get storage quota for a project.","operationId":"get_quota","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Storage quota","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotaResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/trace-summaries":{"get":{"tags":["Traces"],"summary":"Query trace summaries — one row per trace with span count, error count,\nroot span info, and proper trace-level pagination.","operationId":"query_trace_summaries","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"query","description":"Filter by trace ID","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by status (OK, ERROR)","required":false,"schema":{"type":"string"}},{"name":"min_duration_ms","in":"query","description":"Minimum trace duration in ms","required":false,"schema":{"type":"number","format":"double"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"name_pattern","in":"query","description":"Filter by span name pattern (ILIKE)","required":false,"schema":{"type":"string"}},{"name":"sort_by","in":"query","description":"Sort field: 'start_time' (default) or 'duration'","required":false,"schema":{"type":"string"}},{"name":"sort_order","in":"query","description":"Sort direction: 'asc' or 'desc' (default)","required":false,"schema":{"type":"string"}},{"name":"include_total","in":"query","description":"Compute the `total` count (default: true). Set false to skip the second aggregation when only the page is needed","required":false,"schema":{"type":"boolean"}},{"name":"limit","in":"query","description":"Max traces to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Trace summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TraceSummariesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces":{"get":{"tags":["Traces"],"summary":"Query trace spans with optional filters.","description":"Each returned span has a `duration_ms` field (float, milliseconds) — this is\nthe ONLY field guaranteed to be in milliseconds. Spans also carry an\n`attributes` map of raw key/value pairs exactly as reported by the\ninstrumenting library: numeric attribute values may be seconds, milliseconds,\nmicroseconds, or nanoseconds depending on that library's convention, and\nnothing in this response labels the unit. Never assume an attribute's\nnumeric value shares `duration_ms`'s unit, and never state a duration in\nmilliseconds unless it came from a `duration_ms` field.","operationId":"query_traces","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"query","description":"Filter by trace ID","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by status (OK, ERROR, UNSET)","required":false,"schema":{"type":"string"}},{"name":"min_duration_ms","in":"query","description":"Minimum span duration in ms","required":false,"schema":{"type":"number","format":"double"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Max spans to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Trace spans","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TracesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces/cross-project/{trace_id}":{"get":{"tags":["Traces"],"summary":"Discover sibling projects that share the same `trace_id` (Phase 1 banner).","description":"Returns an empty `siblings` list when the trace is single-project — never\n404. Project names are included so the UI can render navigation links\nwithout a second round-trip. See ADR-027 §3 for the full auth model and\ntopology-disclosure trade-offs.","operationId":"getCrossProjectTraceSiblings","parameters":[{"name":"trace_id","in":"path","description":"Trace ID (32 lowercase hex characters)","required":true,"schema":{"type":"string"}},{"name":"exclude_project_id","in":"query","description":"Project ID to exclude (the caller's own project) so the UI does not render a self-link","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Sibling projects sharing this trace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossProjectTraceResponse"}}}},"400":{"description":"trace_id is not 32 lowercase hex characters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions or deployment token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces/{project_id}/{trace_id}":{"get":{"tags":["Traces"],"summary":"Get all spans for a specific trace.","description":"Each span has a `duration_ms` field (float, milliseconds) — the ONLY field\nguaranteed to be in milliseconds — plus an `attributes` map of raw\nkey/value pairs exactly as the instrumenting library reported them.\nNumeric attribute values (e.g. connection-pool wait times, queue delays)\nmay be in seconds, milliseconds, microseconds, or nanoseconds depending on\nthat library's own convention; this response never labels the unit. When\nexplaining what a span spent time on, only quote milliseconds from\n`duration_ms` (or from `start_time`/`end_time` deltas) — never assume a raw\nattribute number is already in milliseconds.","operationId":"get_trace","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"path","description":"Trace ID (hex)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Trace spans tree","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TracesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/v1/logs":{"post":{"tags":["OTel Ingest"],"summary":"Ingest log records via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, routes high-severity logs\nto DB and all logs to S3.","operationId":"ingest_logs","requestBody":{"description":"OTLP ExportLogsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Logs accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/metrics":{"post":{"tags":["OTel Ingest"],"summary":"Ingest metrics via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, then stores.","operationId":"ingest_metrics","requestBody":{"description":"OTLP ExportMetricsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Metrics accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/traces":{"post":{"tags":["OTel Ingest"],"summary":"Ingest trace spans via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, then stores spans.","operationId":"ingest_traces","requestBody":{"description":"OTLP ExportTraceServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Traces accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/logs":{"post":{"tags":["OTel Ingest"],"summary":"Ingest log records with project/environment/deployment in the URL path.","operationId":"ingest_logs_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportLogsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Logs accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/metrics":{"post":{"tags":["OTel Ingest"],"summary":"Ingest metrics with project/environment/deployment in the URL path.","operationId":"ingest_metrics_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportMetricsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Metrics accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/traces":{"post":{"tags":["OTel Ingest"],"summary":"Ingest trace spans with project/environment/deployment in the URL path.","operationId":"ingest_traces_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportTraceServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Traces accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/performance/has-metrics":{"get":{"tags":["Performance"],"summary":"Check if performance metrics exist for a project","operationId":"has_performance_metrics","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully checked performance metrics availability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasMetricsResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/metrics":{"get":{"tags":["Performance"],"summary":"Get performance metrics","operationId":"get_performance_metrics","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved performance metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PerformanceMetricsResponse"}}}},"400":{"description":"Invalid date format or missing parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/metrics-over-time":{"get":{"tags":["Performance"],"summary":"Get metrics over time","operationId":"get_metrics_over_time","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved metrics over time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsOverTimeResponse"}}}},"400":{"description":"Invalid date format or missing parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/page-metrics":{"get":{"tags":["Performance"],"summary":"Get grouped page metrics","operationId":"get_grouped_page_metrics","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"group_by","in":"query","description":"Group by: path, country, region, city, device_type, browser, operating_system","required":true,"schema":{"type":"string"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved grouped page metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupedPageMetricsResponse"}}}},"400":{"description":"Invalid date format, missing parameters, or invalid group_by value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/platform/access-info":{"get":{"tags":["Platform"],"summary":"Get information about how the service is being accessed","description":"Returns details about the server's access mode, public IP address, private IP address,\nand domain creation capabilities. Both IP addresses are always included when available.","operationId":"get_access_info","responses":{"200":{"description":"Service access information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAccessInfo"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/platform/private-ip":{"get":{"tags":["Platform"],"summary":"Get private/local IP address of the server","operationId":"get_private_ip","responses":{"200":{"description":"Successfully retrieved private IP address"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/platform/public-ip":{"get":{"tags":["Platform"],"summary":"Get public IP address of the server","operationId":"get_public_ip","responses":{"200":{"description":"Successfully retrieved public IP address"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/presets":{"get":{"tags":["Presets"],"summary":"List all available presets","operationId":"list_presets","responses":{"200":{"description":"List of available presets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPresetsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/presets/{slug}/dockerfile":{"post":{"tags":["Presets"],"summary":"Generate a Dockerfile from a preset","description":"Returns the Dockerfile content and build arguments for a given preset slug.\nThe CLI can use this to build Docker images locally without needing a Dockerfile\nin the project directory, enabling zero-config deployments.","operationId":"generate_preset_dockerfile","parameters":[{"name":"slug","in":"path","description":"Preset slug (e.g., nextjs, vite, python)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateDockerfileRequest"}}},"required":true},"responses":{"200":{"description":"Generated Dockerfile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateDockerfileResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Preset not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/logs":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_logs","parameters":[{"name":"tail","in":"query","description":"Lines to tail (default 200, max 2000)","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/restart":{"post":{"tags":["Preview Gateway"],"operationId":"restart_preview_gateway","responses":{"204":{"description":"Gateway restarted"}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/settings":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_settings","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewGatewaySettingsResponse"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Preview Gateway"],"operationId":"patch_preview_gateway_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSettingsRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewGatewaySettingsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/status":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_status","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayStatus"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/upgrade":{"post":{"tags":["Preview Gateway"],"operationId":"upgrade_preview_gateway","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeRequest"}}},"required":true},"responses":{"204":{"description":"Gateway upgraded"}},"security":[{"bearer_auth":[]}]}},"/projects":{"get":{"tags":["Projects"],"summary":"Get a list of all projects","operationId":"get_projects","parameters":[{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Number of items per page","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedProjectList"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Projects"],"summary":"Create a new project","operationId":"create_project","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectRequest"}}},"required":true},"responses":{"200":{"description":"Project created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid input"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/by-slug/{slug}":{"get":{"tags":["Projects"],"summary":"Get details of a specific project by slug","operationId":"get_project_by_slug","parameters":[{"name":"slug","in":"path","description":"Project slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Project details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/from-template":{"post":{"tags":["Projects"],"summary":"Create a new project from a template","description":"Creates a new repository from a template and sets up the project with the\nspecified configuration. The template is cloned to a new repository under\nthe authenticated user's account or specified organization.","operationId":"create_project_from_template","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectFromTemplateRequest"}}},"required":true},"responses":{"201":{"description":"Project created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectFromTemplateResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Template not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/statistics":{"get":{"tags":["Projects"],"summary":"Get project statistics","operationId":"get_project_statistics","responses":{"200":{"description":"Project statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectStatisticsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}":{"get":{"tags":["Projects"],"summary":"Get details of a specific project","operationId":"get_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Project details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Projects"],"operationId":"update_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectRequest"}}},"required":true},"responses":{"200":{"description":"Project updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Projects"],"operationId":"delete_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Project deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}/deployments":{"get":{"tags":["Projects"],"operationId":"get_project_deployments","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"environment_id","in":"query","description":"Environment ID filter","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of deployments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentListResponse"}}}},"404":{"description":"Project not found"}}}},"/projects/{id}/last-deployment":{"get":{"tags":["Deployments"],"summary":"Get the last deployment for a specific project","operationId":"get_last_deployment","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Last deployment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project not found or no deployments"},"500":{"description":"Internal server error"}}}},"/projects/{id}/source":{"patch":{"tags":["Projects"],"summary":"Change a project's source type to a Git-less type (docker_image /\nstatic_files / manual). Switching TO Git is done via the Git settings\nendpoint (`POST /projects/{id}/git`), which also supplies the repository and\nprovider connection.","operationId":"change_project_source","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeProjectSourceRequest"}}},"required":true},"responses":{"200":{"description":"Source type changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid source type change (e.g. switching to Git here)"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}/trigger-pipeline":{"post":{"tags":["Projects"],"summary":"Trigger pipeline for a specific project","operationId":"trigger_project_pipeline","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerPipelinePayload"}}},"required":true},"responses":{"200":{"description":"Pipeline triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerPipelineResponse"}}}},"400":{"description":"Invalid request"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/active-visitors":{"get":{"tags":["Events"],"summary":"Get active visitors count","operationId":"get_active_visitors","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved active visitors count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveVisitorsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents":{"get":{"tags":["Agents"],"operationId":"list_agents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of agents for project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAgentsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAgentRequest"}}},"required":true},"responses":{"201":{"description":"Agent created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/cli-status":{"get":{"tags":["Agents"],"operationId":"get_cli_status","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"provider","in":"query","description":"AI provider: claude_cli or codex_cli","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"CLI status"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs":{"get":{"tags":["Agents"],"operationId":"list_all_runs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of all agent runs for a project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRunsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/latest-for-source":{"get":{"tags":["Agents"],"operationId":"latest_run_for_source","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trigger_source_type","in":"query","description":"Trigger source type, e.g. 'error_group'","required":true,"schema":{"type":"string"}},{"name":"trigger_source_id","in":"query","description":"Trigger source ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest matching run, or null if none","content":{"application/json":{"schema":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AgentRunResponse"}]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}":{"get":{"tags":["Agents"],"operationId":"get_run_with_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run with logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunWithLogsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/cancel":{"post":{"tags":["Agents"],"operationId":"cancel_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Agent run ID to cancel","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Run is already in a terminal state"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/retry":{"post":{"tags":["Agents"],"summary":"Retry a completed, failed, cancelled, or no_fix run with the same trigger context.\nCreates a new run record and spawns the executor.","operationId":"retry_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID to retry","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"New run created from retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Run is still active"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/stream":{"get":{"tags":["Agents"],"summary":"SSE endpoint for real-time streaming of run events.\nPolls the agent_run_logs table every 500ms for new entries and streams them.\nCloses when the run reaches a terminal status.","operationId":"stream_run_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Agent run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Server-Sent Events stream of run log events and terminal status","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/sandbox-status":{"get":{"tags":["Agents"],"operationId":"get_sandbox_status","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Project-scoped sandbox readiness (Docker + agent image)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/smoke-test":{"post":{"tags":["Agents"],"summary":"Run a smoke test to verify the selected AI CLI works in the environment\nwhere agents will actually execute (host or sandbox container). If no\n`provider_id` is supplied the globally active provider is tested.","operationId":"smoke_test_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"provider_id","in":"query","description":"Provider id to test; defaults to the globally active provider","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Smoke test result for the AI CLI in the agent's execution environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmokeTestResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}":{"get":{"tags":["Agents"],"operationId":"get_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Agent config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAgentRequest"}}},"required":true},"responses":{"200":{"description":"Agent updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Agent deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}/runs":{"get":{"tags":["Agents"],"operationId":"list_agent_runs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of runs for a specific agent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRunsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}/trigger":{"post":{"tags":["Agents"],"operationId":"trigger_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerAgentRequest"}}},"required":true},"responses":{"202":{"description":"Agent run created and queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"402":{"description":"Daily budget exceeded"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"422":{"description":"AI CLI not installed"},"429":{"description":"Cooldown active"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/aggregated-buckets":{"get":{"tags":["Events"],"summary":"Get aggregated metrics by time bucket","operationId":"get_aggregated_buckets","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for the query range","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for the query range","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Optional deployment filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Time bucket size: '1 hour', '1 day', '1 week', etc. (default: '1 hour')","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved aggregated buckets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AggregatedBucketsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations":{"get":{"tags":["AI Chat"],"summary":"Find the existing chat for a context (returns `null` if none yet). Requires\nthe per-project `ai_debug_chat_enabled` toggle to be on; returns 403 when the\nfeature is disabled so revoking it consistently hides existing chat content.","operationId":"find_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"context_type","in":"query","required":true,"schema":{"type":"string"}},{"name":"context_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ConversationResponse"}]}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]},"post":{"tags":["AI Chat"],"summary":"Get-or-create the chat for a context (seeds it on first open).","operationId":"create_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversationRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/list":{"get":{"tags":["AI Chat"],"summary":"List all active conversations for a project, most-recently-active first.\nPowers the conversation switcher in the AI assistant sidebar.","operationId":"list_conversations","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationResponse"}}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}":{"get":{"tags":["AI Chat"],"summary":"Full conversation history (excluding the internal system seed).","operationId":"get_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDetailResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AI Chat"],"summary":"Rename a conversation (set its human-facing title).","operationId":"rename_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameConversationRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationResponse"}}}},"400":{"description":""},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/archive":{"post":{"tags":["AI Chat"],"summary":"Archive (soft-delete) a conversation.","operationId":"archive_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/messages":{"post":{"tags":["AI Chat"],"summary":"Send a user message; stream the assistant reply as Server-Sent Events.","operationId":"send_message","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageRequest"}}},"required":true},"responses":{"200":{"description":"SSE stream of assistant text deltas","content":{"text/event-stream":{}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/pending-actions":{"get":{"tags":["AI Chat"],"summary":"List all pending actions for a conversation (most-recently-proposed first).","operationId":"list_pending_actions","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","description":"Conversation public id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PendingActionResponse"}}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}":{"get":{"tags":["AI Chat"],"summary":"Get a single pending action by its public id (scoped to the project).","operationId":"get_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}/confirm":{"post":{"tags":["AI Chat"],"summary":"Confirm a proposed AI action: validate permission, atomically claim, execute,\npersist outcome. The execution uses the CONFIRMING user's auth — never the model's.","operationId":"confirm_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"409":{"description":""},"503":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}/reject":{"post":{"tags":["AI Chat"],"summary":"Reject a proposed AI action (no execution). Status transitions to \"rejected\".","operationId":"reject_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"409":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms":{"get":{"tags":["Alarms"],"summary":"List alarms for a project with optional filters.","operationId":"listProjectAlarms","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_type","in":"query","description":"Filter by alarm type (e.g. `container_restart`, `outage`).","required":false,"schema":{"type":["string","null"]}},{"name":"status","in":"query","description":"Filter by status: `firing`, `acknowledged`, or `resolved`.","required":false,"schema":{"type":["string","null"]}},{"name":"severity","in":"query","description":"Filter by severity: `info`, `warning`, or `critical`.","required":false,"schema":{"type":["string","null"]}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"service_id","in":"query","description":"Filter by external service ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based, default 1).","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default 20, max 100).","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated list of alarms","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/summary":{"get":{"tags":["Alarms"],"summary":"Get alarm counts by status/severity/type for a project (dashboard summary widget).","operationId":"getProjectAlarmsSummary","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm summary counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmSummaryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/{alarm_id}/acknowledge":{"post":{"tags":["Alarms"],"summary":"Acknowledge a firing alarm (marks it as seen but not resolved).","operationId":"acknowledgeAlarm","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_id","in":"path","description":"Alarm ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm acknowledged"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alarm not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/{alarm_id}/resolve":{"post":{"tags":["Alarms"],"summary":"Resolve an alarm.","operationId":"resolveAlarm","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_id","in":"path","description":"Alarm ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm resolved"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alarm not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/analyze":{"post":{"tags":["Autofixer"],"summary":"Start an autofixer analysis run for the given error group.\nCreates the run record immediately and spawns analysis in the background.","operationId":"start_analysis","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAnalysisRequest"}}},"required":true},"responses":{"202":{"description":"Analysis started; returns run_id for streaming","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutofixerRunResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}":{"get":{"tags":["Autofixer"],"summary":"Get a single autofixer run with its logs.","operationId":"get_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run with logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutofixerRunWithLogsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/add-context":{"post":{"tags":["Autofixer"],"summary":"Append a user message to the run's context field.","operationId":"add_context","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddContextRequest"}}},"required":true},"responses":{"200":{"description":"Context appended"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/cancel":{"post":{"tags":["Autofixer"],"summary":"Cancel an autofixer run and clean up the work directory.","operationId":"cancel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run cancelled"},"400":{"description":"Run is already in a terminal state"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/create-pr":{"post":{"tags":["Autofixer"],"summary":"Push the fix branch and create a pull request.\nRequires phase == \"fix_ready\".","operationId":"create_pr","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"201":{"description":"PR created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePrResponse"}}}},"400":{"description":"Run not in fix_ready phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/fix":{"post":{"tags":["Autofixer"],"summary":"Transition from analysis to fix phase.\nRequires phase == \"analyzed\".","operationId":"start_fix","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Fix generation started"},"400":{"description":"Run not in analyzed phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/re-analyze":{"post":{"tags":["Autofixer"],"summary":"Continue the conversation with user feedback.\nUses the same Claude session (--continue) in the existing work directory.\nRequires phase == \"analyzed\".","operationId":"re_analyze","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Conversation continued with feedback"},"400":{"description":"Run not in analyzed phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/stream":{"get":{"tags":["Agents"],"summary":"SSE endpoint: streams run log events in real-time.\nPolls every 500 ms. Keeps the connection open through \"analyzed\" and \"fix_ready\"\nwaiting states; closes only on terminal statuses.","operationId":"stream_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Autofixer run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Server-Sent Events stream of autofixer run logs and status updates","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/automatic-deploy":{"post":{"tags":["Projects"],"summary":"Update automatic deployment setting for a project","operationId":"update_automatic_deploy","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAutomaticDeployRequest"}}},"required":true},"responses":{"200":{"description":"Automatic deployment setting updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains":{"get":{"tags":["Custom Domains"],"summary":"List all custom domains for a project","operationId":"list_custom_domains_for_project","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domains retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCustomDomainsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Custom Domains"],"summary":"Create a custom domain for a project","operationId":"create_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainRequest"}}},"required":true},"responses":{"201":{"description":"Custom domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"409":{"description":"Domain already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains/{domain_id}":{"get":{"tags":["Custom Domains"],"summary":"Get a custom domain by ID","operationId":"get_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domain retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Custom Domains"],"summary":"Update a custom domain","operationId":"update_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomDomainRequest"}}},"required":true},"responses":{"200":{"description":"Custom domain updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Custom Domains"],"summary":"Delete a custom domain","operationId":"delete_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Custom domain deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains/{domain_id}/link-certificate/{certificate_id}":{"post":{"tags":["Custom Domains"],"summary":"Link a custom domain to a certificate","operationId":"link_custom_domain_to_certificate","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"certificate_id","in":"path","description":"Certificate ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domain linked to certificate successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain or certificate not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-config":{"patch":{"tags":["Projects"],"summary":"Update deployment configuration for a project","operationId":"update_project_deployment_config","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeploymentConfigRequest"}}},"required":true},"responses":{"200":{"description":"Deployment configuration updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid deployment configuration"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens":{"get":{"tags":["Deployment Tokens"],"summary":"List all deployment tokens for a project","operationId":"list_deployment_tokens","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of deployment tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Deployment Tokens"],"summary":"Create a new deployment token for a project","operationId":"create_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenRequest"}}},"required":true},"responses":{"201":{"description":"Deployment token created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Token with this name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens/{token_id}":{"get":{"tags":["Deployment Tokens"],"summary":"Get a specific deployment token","operationId":"get_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment token details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Deployment Tokens"],"summary":"Delete a deployment token","operationId":"delete_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Deployment token deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Deployment Tokens"],"summary":"Update a deployment token","operationId":"update_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeploymentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Deployment token updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"409":{"description":"Token with this name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens/{token_id}/rotate":{"post":{"tags":["Deployment Tokens"],"summary":"Rotate a deployment token, invalidating its old secret and issuing a new one","operationId":"rotate_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment token rotated successfully; the response contains the new plaintext token, shown only once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}":{"get":{"tags":["Deployments"],"summary":"Get a specific deployment by ID for a project (identified by ID or slug)","operationId":"get_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/cancel":{"post":{"tags":["Projects"],"summary":"Cancel a deployment","operationId":"cancel_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment cancelled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"400":{"description":"Deployment cannot be cancelled (already completed, failed, or cancelled)"},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/container-logs":{"get":{"tags":["Deployments"],"summary":"List the captured (historical) container-log dumps for a deployment.","description":"Container runtime logs are normally only available live from the running\ncontainer. When a deployment is superseded its containers are torn down and\nthose logs would be lost — so just before teardown we capture each\ncontainer's logs to durable storage. This endpoint lists what was captured\nfor a given (often older) deployment, so a user can read the logs of a\ncontainer that no longer exists.","operationId":"list_deployment_container_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Captured container logs for the deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentContainerLogsListResponse"}}}},"404":{"description":"Deployment not found in this project"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/container-logs/{log_id}":{"get":{"tags":["Deployments"],"summary":"Get the captured text content of a single historical container-log dump.","operationId":"get_deployment_container_log_content","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"log_id","in":"path","description":"Captured log ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Captured container log content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentContainerLogContentResponse"}}}},"404":{"description":"Captured log not found in this project"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/jobs":{"get":{"tags":["Deployments"],"summary":"Get jobs for a specific deployment","description":"Returns all jobs (workflow tasks) for a deployment, ordered by execution order.\nThis replaces the old deployment stages endpoint.","operationId":"get_deployment_jobs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Jobs retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentJobsResponse"}}}},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/jobs/{job_id}/logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a specific deployment job","operationId":"get_deployment_job_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"job_id","in":"path","description":"Job ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job logs retrieved successfully","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Job or logs not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/jobs/{job_id}/logs/tail":{"get":{"tags":["Deployments"],"summary":"Tail logs for a specific deployment job in real-time via WebSocket","description":"**WebSocket Streaming**: Logs are sent as raw text, one line per WebSocket message.\n\n**Authentication**: Requires authentication via session cookie (browser clients)\nor API key (API clients). For browser-based WebSocket connections, ensure the user\nis logged in - the browser automatically includes session cookies in the WebSocket\nupgrade request.\n\n**API Client Authentication**: Include API key in Authorization header:\n```text\nAuthorization: Bearer tk_your_api_key_here\n```","operationId":"tail_deployment_job_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"job_id","in":"path","description":"Job ID","required":true,"schema":{"type":"string"}}],"responses":{"101":{"description":"WebSocket connection established for streaming deployment job logs"},"404":{"description":"Job or logs not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/operations":{"get":{"tags":["Deployments"],"summary":"Get all operations for a deployment","operationId":"get_deployment_operations","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of operations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Deployments"],"summary":"Execute a deployment operation (deploy, mark_complete, take_screenshot)","operationId":"execute_deployment_operation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteOperationRequest"}}},"required":true},"responses":{"202":{"description":"Operation executed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"400":{"description":"Invalid operation"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/operations/{operation_type}":{"get":{"tags":["Deployments"],"summary":"Get the status of a specific operation type","operationId":"get_deployment_operation_status","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"operation_type","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Operation status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Operation not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/pause":{"post":{"tags":["Projects"],"summary":"Pause a deployment","operationId":"pause_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment paused successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/promote":{"post":{"tags":["Deployments"],"summary":"Promote a deployment to another environment","description":"Creates a new deployment in the target environment using the source deployment's\nDocker image. Useful for promoting a validated preview/staging deployment to production.","operationId":"promote_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Source deployment ID to promote","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteDeploymentRequest"}}},"required":true},"responses":{"200":{"description":"Promotion initiated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"400":{"description":"Invalid deployment state for promotion"},"404":{"description":"Project, deployment, or target environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/resume":{"post":{"tags":["Projects"],"summary":"Resume a deployment","operationId":"resume_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment resumed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/rollback":{"post":{"tags":["Projects"],"operationId":"rollback_to_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID to rollback to","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Rollback initiated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/teardown":{"delete":{"tags":["Projects"],"summary":"Teardown a specific deployment","operationId":"teardown_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Deployment torn down successfully"},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/dsns":{"get":{"tags":[],"summary":"List all DSNs for a project","operationId":"list_dsns","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of DSNs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":[],"summary":"Create a new DSN for a project","operationId":"create_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDSNRequest"}}},"required":true},"responses":{"201":{"description":"DSN created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/get-or-create":{"post":{"tags":[],"summary":"Get or create DSN for a project/environment/deployment combination","operationId":"get_or_create_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrCreateDSNRequest"}}},"required":true},"responses":{"200":{"description":"DSN retrieved or created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/{dsn_id}/regenerate":{"post":{"tags":[],"summary":"Regenerate DSN keys (rotate keys)","operationId":"regenerate_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"dsn_id","in":"path","description":"DSN ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegenerateDSNRequest"}}},"required":true},"responses":{"200":{"description":"DSN keys regenerated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"DSN not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/{dsn_id}/revoke":{"post":{"tags":[],"summary":"Revoke (deactivate) a DSN","operationId":"revoke_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"dsn_id","in":"path","description":"DSN ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"DSN revoked"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"DSN not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/env-vars":{"get":{"tags":["Projects"],"summary":"Get environment variables for a project, optionally filtered by environment","operationId":"get_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment ID to filter by","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Create a new environment variable","operationId":"create_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnvironmentVariableRequest"}}},"required":true},"responses":{"201":{"description":"Environment variables created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/resolved":{"get":{"tags":["Projects"],"summary":"Resolved env vars for a project (manual + integration-sourced, merged).","description":"Returns the effective set of environment variables a deployment would see,\ncombining manually-defined vars with those contributed by linked external\nservices (Postgres, Redis, S3, etc.). Each entry is tagged with its source\nso the UI can render an integration icon, and manual entries that shadow an\nintegration key carry a reference to the integration they override.\n\nValues are always returned as a masked preview. Use the per-key reveal\nendpoint for plaintext (audit-logged).","operationId":"get_resolved_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment ID to filter manual vars by","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Resolved environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ResolvedEnvVarResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/resolved/{key}/value":{"get":{"tags":["Projects"],"summary":"Reveal the plaintext value of a resolved environment variable.","description":"Mirrors `GET /projects/{id}/env-vars/{key}/value` but handles keys sourced\nfrom linked integrations (which are not stored in the `env_vars` table).\nResolution order mirrors the merged view:\n\n1. Manual env var with this key — this endpoint reads the manual store when\n the key exists there, then writes its own reveal audit event so callers\n can safely use one endpoint regardless of source.\n2. Integration env var supplied by a linked external service.\n\nReturns 404 when neither a manual var nor an integration produces the key.","operationId":"get_resolved_environment_variable_value","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Environment variable key","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"query","description":"Exact manual environment-variable row ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"service_id","in":"query","description":"Integration service ID shown by the resolved list","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Resolved environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Project, key, or integration not found"},"409":{"description":"Environment variable key is ambiguous"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/{key}/value":{"get":{"tags":["Projects"],"summary":"Get environment variable value by key","operationId":"get_environment_variable_value","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Environment variable key","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"query","description":"Exact environment-variable row ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Project or variable not found"},"409":{"description":"Environment variable key is ambiguous"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/{var_id}":{"put":{"tags":["Projects"],"summary":"Update an environment variable","operationId":"update_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"path","description":"Environment variable ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentVariableRequest"}}},"required":true},"responses":{"200":{"description":"Environment variables updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project or variable not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Projects"],"summary":"Delete an environment variable","operationId":"delete_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"path","description":"Environment variable ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment variable deleted successfully"},"404":{"description":"Project or variable not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments":{"get":{"tags":["Projects"],"summary":"Get all environments for a project","operationId":"get_environments","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Create a new environment for a project","operationId":"create_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnvironmentRequest"}}},"required":true},"responses":{"201":{"description":"Environment created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}":{"get":{"tags":["Projects"],"summary":"Get a specific environment by ID or slug","operationId":"get_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Projects"],"summary":"Delete an environment permanently","description":"Permanently deletes an environment and all related data. Cannot delete:\n- Production environments (name = \"Production\")\n\nWarning: This action is permanent and cannot be undone.\nActive deployments are automatically cancelled before deletion.","operationId":"delete_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment permanently deleted"},"400":{"description":"Cannot delete production environment"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons":{"get":{"tags":["Crons"],"operationId":"get_environment_crons","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of cron jobs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CronInfo"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons/{cron_id}":{"get":{"tags":["Crons"],"operationId":"get_cron_by_id","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"cron_id","in":"path","description":"Cron Job ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cron job details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CronInfo"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Cron job not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons/{cron_id}/executions":{"get":{"tags":["Crons"],"operationId":"get_cron_executions","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"cron_id","in":"path","description":"Cron Job ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"List of cron job executions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CronExecutionInfo"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Cron job not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/domains":{"get":{"tags":["Projects"],"summary":"Get all environment domains for a specific environment","operationId":"get_environment_domains","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentDomainResponse"}}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Add a new environment domain","operationId":"add_environment_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEnvironmentDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentDomainResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/domains/{domain_id}":{"delete":{"tags":["Projects"],"summary":"Delete an environment domain","operationId":"delete_environment_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Domain deleted successfully"},"404":{"description":"Project, environment, or domain not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/settings":{"put":{"tags":["Projects"],"summary":"Update environment settings","operationId":"update_environment_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Environment settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/sleep":{"post":{"tags":["Environments"],"summary":"Sleep an on-demand environment","description":"Manually put an on-demand environment to sleep. Stops containers and sets\n`sleeping = true`. If no OnDemandWaker is available, falls back to DB flag only.","operationId":"sleep_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment put to sleep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"On-demand not enabled for this environment"},"404":{"description":"Environment not found"},"429":{"description":"Too many state transitions, retry after cooldown"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/subdomain":{"patch":{"tags":["Projects"],"summary":"Rename the auto-managed subdomain for an environment.","description":"Replaces the environment's previous subdomain entirely — the old\nhostname stops resolving once the proxy reloads its route table.\nCustom domains attached to the environment are unaffected.","operationId":"update_environment_subdomain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentSubdomainRequest"}}},"required":true},"responses":{"200":{"description":"Subdomain updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"Invalid subdomain or conflict with another environment"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/teardown":{"delete":{"tags":["Projects"],"summary":"Teardown an environment and all its active deployments","operationId":"teardown_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment torn down successfully"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/wake":{"post":{"tags":["Environments"],"summary":"Wake a sleeping on-demand environment","description":"Manually wake an environment that has been put to sleep by the on-demand\nidle timeout. Starts containers, waits for health checks, then sets\n`sleeping = false`. If no OnDemandWaker is available (proxy not running\nin same process), falls back to setting the DB flag only.","operationId":"wake_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment woken up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"On-demand not enabled for this environment"},"404":{"description":"Environment not found"},"429":{"description":"Too many state transitions, retry after cooldown"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/container-logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a container in an environment via WebSocket","operationId":"get_container_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"end_date","in":"query","description":"End date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tail","in":"query","description":"Number of lines to tail (or 'all')","required":false,"schema":{"type":"string"}},{"name":"container_name","in":"query","description":"Optional container name (defaults to first/primary container)","required":false,"schema":{"type":"string"}},{"name":"timestamps","in":"query","description":"Include timestamps in log output (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"follow","in":"query","description":"Follow log output in real-time (default: true)","required":false,"schema":{"type":"boolean"}}],"responses":{"101":{"description":"WebSocket connection established for streaming container logs"},"400":{"description":"Not a server-type project"},"404":{"description":"Project, deployment, or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers":{"get":{"tags":["Deployments"],"summary":"List all containers for an environment","operationId":"list_containers","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of containers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerListResponse"}}}},"400":{"description":"Not a server-type project"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}":{"get":{"tags":["Containers"],"summary":"Get detailed information about a specific container","operationId":"get_container_detail","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerDetailResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/environment/{variable_name}":{"get":{"tags":["Containers"],"operationId":"get_container_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"variable_name","in":"path","description":"Environment variable name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerEnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Container or environment variable not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a specific container by container ID via WebSocket","operationId":"get_container_logs_by_id","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"end_date","in":"query","description":"End date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tail","in":"query","description":"Number of lines to tail (or 'all')","required":false,"schema":{"type":"string"}},{"name":"timestamps","in":"query","description":"Include timestamps in log output (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"follow","in":"query","description":"Follow log output in real-time (default: true)","required":false,"schema":{"type":"boolean"}}],"responses":{"101":{"description":"WebSocket connection established for streaming container logs"},"400":{"description":"Not a server-type project"},"404":{"description":"Project, environment, or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics":{"get":{"tags":["Containers"],"summary":"Get metrics/stats for a specific container","operationId":"get_container_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container metrics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerMetricsResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics/history":{"get":{"tags":["Containers"],"summary":"Fetch a time-series range for a single container resource metric\n(recorded by the container health monitor every ~30s).","description":"Useful metric names: `container.cpu_percent`,\n`container.cpu_utilization_percent`, `container.memory_used_bytes`,\n`container.memory_percent`, `container.network_rx_bytes_delta`,\n`container.network_tx_bytes_delta`.","operationId":"ContainerMetricsGetHistory","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"metric","in":"query","description":"Dotted metric name, e.g. `container.cpu_percent` or\n`container.memory_used_bytes`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `1h`, `6h`, `24h`, or `7d` (defaults to `1h`).","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerMetricHistoryPoint"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Container not found"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics/stream":{"get":{"tags":["Containers"],"summary":"Stream container metrics via Server-Sent Events (SSE)","operationId":"stream_container_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"interval","in":"query","description":"Update interval in milliseconds (default: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Metrics stream established (Server-Sent Events)"},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/restart":{"post":{"tags":["Containers"],"summary":"Restart a container","operationId":"restart_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container restarted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/start":{"post":{"tags":["Containers"],"summary":"Start a container","operationId":"start_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/stop":{"post":{"tags":["Containers"],"summary":"Stop a specific container","operationId":"stop_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container stopped successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/deploy/image":{"post":{"tags":["Deployments"],"summary":"Deploy from an external Docker image","description":"Triggers a deployment using a pre-built Docker image from an external registry.\nThe image will be pulled and deployed to the specified environment.","operationId":"deploy_from_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployFromImageRequest"}}},"required":true},"responses":{"202":{"description":"Deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/deploy/image-upload":{"post":{"tags":["Deployments"],"summary":"Deploy from an uploaded Docker image tarball","description":"Uploads a Docker image tarball (from `docker save`) and deploys it directly.\nThe image is imported using `docker load` and then deployed to the specified environment.\nThis is useful when you want to deploy an image without pushing to a registry first.\n\nThe uploaded file should be a tarball created by `docker save myimage:tag > image.tar`\nor `docker save myimage:tag | gzip > image.tar.gz` (gzip compressed tarballs are also supported).","operationId":"deploy_from_image_upload","parameters":[{"name":"tag","in":"query","description":"Tag to apply to the imported image (e.g., \"myapp:v1.0\")\nIf not provided, a unique tag will be generated","required":false,"schema":{"type":["string","null"]}},{"name":"health_check_path","in":"query","description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nMust start with '/'. When omitted, defaults to \"/\".","required":false,"schema":{"type":["string","null"]}},{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Image imported and deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request or unsupported format"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project or environment not found"},"413":{"description":"Image tarball too large"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/deploy/static":{"post":{"tags":["Deployments"],"summary":"Deploy from an uploaded static bundle","description":"Triggers a deployment using a previously uploaded static file bundle.","operationId":"deploy_from_static","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployFromStaticRequest"}}},"required":true},"responses":{"202":{"description":"Deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project, environment, or bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/error-alert-rules":{"get":{"tags":["error-alert-rules"],"summary":"List all alert rules for a project","operationId":"list_alert_rules","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of alert rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlertRuleResponse"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["error-alert-rules"],"summary":"Create a new alert rule","operationId":"create_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertRuleRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"400":{"description":"Validation error"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-alert-rules/{rule_id}":{"get":{"tags":["error-alert-rules"],"summary":"Get a specific alert rule","operationId":"get_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alert rule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["error-alert-rules"],"summary":"Update an existing alert rule","operationId":"update_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertRuleRequest"}}},"required":true},"responses":{"200":{"description":"Alert rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["error-alert-rules"],"summary":"Delete an alert rule","operationId":"delete_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-dashboard-stats":{"get":{"tags":["error-tracking"],"summary":"Get error dashboard statistics","operationId":"get_error_dashboard_stats","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"end_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"environment_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"compare_to_previous","in":"query","required":false,"schema":{"type":["boolean","null"]}}],"responses":{"200":{"description":"Error dashboard statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDashboardStatsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups":{"get":{"tags":["error-tracking"],"summary":"List error groups for a project","operationId":"list_error_groups","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"status","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"environment_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_date","in":"query","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"end_date","in":"query","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of error groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedErrorGroupsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}":{"get":{"tags":["error-tracking"],"summary":"Get a specific error group","operationId":"get_error_group","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error group details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorGroupResponse"}}}},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["error-tracking"],"summary":"Update error group status","operationId":"update_error_group","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateErrorGroupRequest"}}},"required":true},"responses":{"200":{"description":"Error group updated successfully"},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}/events":{"get":{"tags":["error-tracking"],"summary":"List error events for a specific group","operationId":"list_error_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated list of error events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedErrorEventsResponse"}}}},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}/events/{event_id}":{"get":{"tags":["error-tracking"],"summary":"Get a specific error event","operationId":"get_error_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"event_id","in":"path","description":"Error event ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Error event details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEventResponse"}}}},"404":{"description":"Event not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-stats":{"get":{"tags":["error-tracking"],"summary":"Get error statistics for a project","operationId":"get_error_stats","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorGroupStatsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-time-series":{"get":{"tags":["error-tracking"],"summary":"Get error time series data for charts","operationId":"get_error_time_series","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"end_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"bucket","in":"query","description":"Time bucket size (e.g., \"1h\", \"15m\", \"1d\", \"1 hour\", \"30 minutes\")","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Error time series data","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ErrorTimeSeriesDataResponse"}}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/events":{"get":{"tags":["Events"],"summary":"Get event counts with filtering","operationId":"get_events_count","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of events to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"custom_events_only","in":"query","description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event counts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventCount"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/breakdown":{"get":{"tags":["Events"],"summary":"Get event type breakdown","operationId":"get_event_type_breakdown","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event type breakdown","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTypeBreakdown"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/ingest":{"post":{"tags":["Events"],"summary":"Record an analytics event via the console API with explicit project ID.","description":"The app backend forwards the user's encrypted Temps cookies, so visitor/session\nidentity is resolved automatically by middleware. No geolocation or user-agent\nenrichment is performed — this is a lightweight server-side ingestion path.","operationId":"record_console_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsoleEventPayload"}}},"required":true},"responses":{"200":{"description":"Event recorded successfully"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/properties/breakdown":{"get":{"tags":["Events"],"summary":"Get property breakdown by grouping events by a column","operationId":"get_property_breakdown","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Column to group by (channel, device_type, browser, etc.)","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by event name","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors - default: events","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of results (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"filter_country","in":"query","description":"Filter by country (for region/city drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter by region (for city drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter by browser name (for version drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_os","in":"query","description":"Filter by OS name (for version drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"Filter by channel name (for channel drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"Filter by referrer hostname (for referrer drill-downs)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved property breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyBreakdownResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/properties/timeline":{"get":{"tags":["Events"],"summary":"Get property timeline by grouping events by a column over time","operationId":"get_property_timeline","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Column to group by (channel, device_type, browser, etc.)","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by event name","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors - default: events","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Time bucket: hour, day, week, month (default: auto-detect)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved property timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyTimelineResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/timeline":{"get":{"tags":["Events"],"summary":"Get events timeline","operationId":"get_events_timeline","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by specific event name","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Bucket size: hour, day, or week (auto-detected if not specified)","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved events timeline","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/unique":{"get":{"tags":["Funnels"],"summary":"Get all unique/distinct event types for a project (paginated)","operationId":"get_unique_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Unique event types retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventTypesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/external-images":{"get":{"tags":["External Images"],"summary":"List external images for a project","operationId":"list_remote_external_images","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of external images","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedExternalImagesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["External Images"],"summary":"Register an external Docker image","description":"Registers an external Docker image reference without triggering a deployment.\nThe image can be deployed later using the deploy/image endpoint.","operationId":"register_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterImageRequest"}}},"required":true},"responses":{"201":{"description":"Image registered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalImageResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/external-images/{image_id}":{"get":{"tags":["External Images"],"summary":"Get details of a specific external image","operationId":"get_remote_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Image details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalImageResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["External Images"],"summary":"Delete an external image","operationId":"delete_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Image deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/flags":{"get":{"tags":["Feature Flags"],"operationId":"list_flags","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"include_archived","in":"query","description":"Include archived flags. Defaults to false.","required":false,"schema":{"type":"boolean"}},{"name":"page","in":"query","description":"1-indexed page number. Defaults to 1.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page. Defaults to 20, capped at 100.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"Flags listed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Feature Flags"],"operationId":"create_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFlagRequest"}}},"required":true},"responses":{"201":{"description":"Flag created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Flag key already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/flags/{key}":{"get":{"tags":["Feature Flags"],"operationId":"get_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Flag retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Feature Flags"],"operationId":"archive_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Flag archived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveFlagResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Feature Flags"],"operationId":"update_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFlagRequest"}}},"required":true},"responses":{"200":{"description":"Flag updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/flags/{key}/environments/{environment_id}":{"put":{"tags":["Feature Flags"],"summary":"Set a flag's value in one environment, and/or flip its kill switch.","operationId":"set_flag_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetFlagEnvironmentRequest"}}},"required":true},"responses":{"200":{"description":"Environment value set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagEnvironmentResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag or environment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels":{"get":{"tags":["Funnels"],"summary":"List all funnels for a project","operationId":"list_funnels","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Funnels retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FunnelResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Funnels"],"summary":"Create a new funnel","operationId":"create_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"201":{"description":"Funnel created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/preview":{"post":{"tags":["Funnels"],"summary":"Preview funnel metrics without creating the funnel","operationId":"preview_funnel_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"200":{"description":"Funnel metrics preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunnelMetricsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/{funnel_id}":{"put":{"tags":["Funnels"],"summary":"Update a funnel","operationId":"update_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"200":{"description":"Funnel updated successfully"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Funnels"],"summary":"Delete a funnel","operationId":"delete_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Funnel deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/{funnel_id}/metrics":{"get":{"tags":["Funnels"],"summary":"Get funnel metrics","operationId":"get_funnel_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"country_code","in":"query","description":"Country code filter","required":false,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date filter (ISO 8601)","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date filter (ISO 8601)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Funnel metrics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunnelMetricsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/git":{"post":{"tags":["Projects"],"summary":"Update git settings for a project","operationId":"update_git_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGitSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Git settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid git configuration or branch does not exist"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/gitlab/reinstall-webhook":{"post":{"tags":["Projects"],"summary":"Reinstall the GitLab webhook for a project","description":"Removes the existing webhook (if any) and installs a fresh one.\nUse this when a webhook has been manually deleted on the GitLab side\nand automatic deployments have stopped working.","operationId":"reinstall_gitlab_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Webhook reinstalled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReinstallWebhookResponse"}}}},"400":{"description":"Project is not connected to a GitLab repository"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/has-error-groups":{"get":{"tags":["error-tracking"],"summary":"Check if project has any error groups","operationId":"has_error_groups","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error groups existence check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasErrorGroupsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/has-events":{"get":{"tags":["Events"],"summary":"Check if project has any analytics events","operationId":"has_analytics_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully checked for events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasEventsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/hourly-visits":{"get":{"tags":["Events"],"summary":"Get hourly visits","operationId":"get_hourly_visits","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering visits","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering visits","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events (page views), sessions (unique sessions), or visitors (unique visitors) - default: events","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved hourly visits","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images":{"get":{"tags":["External Images"],"summary":"List all external images for a project","operationId":"list_external_images","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of external images","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images/push":{"post":{"tags":["External Images"],"summary":"Push an external Docker image","operationId":"push_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushImageRequest"}}},"required":true},"responses":{"201":{"description":"Image pushed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images/{image_id}":{"get":{"tags":["External Images"],"summary":"Get details of a specific external image","operationId":"get_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Image details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/incidents":{"get":{"tags":["Status Page"],"summary":"List incidents for a project","operationId":"list_incidents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"status","in":"query","description":"Filter by status","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved incidents"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Status Page"],"summary":"Create a new incident","operationId":"create_incident","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIncidentRequest"}}},"required":true},"responses":{"201":{"description":"Incident created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/incidents/bucketed":{"get":{"tags":["Status Page"],"summary":"Get bucketed incident data for a project","operationId":"get_bucketed_incidents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"interval","in":"query","description":"Bucket interval: '5min', 'hourly', or 'daily' (default: hourly)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) (default: 7 days ago)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) (default: now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved bucketed incident data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentBucketedResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/logs":{"delete":{"tags":["Logs"],"summary":"Purge all logs for a project before a given timestamp","operationId":"purge_project_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurgeLogsRequest"}}},"required":true},"responses":{"200":{"description":"Purge completed"},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers":{"get":{"tags":["Agents"],"operationId":"list_mcps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMcpsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMcpRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers/{slug}":{"get":{"tags":["Agents"],"operationId":"get_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMcpRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"MCP server deleted"},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers/{slug}/config/{field}":{"get":{"tags":["Agents"],"operationId":"reveal_mcp_config","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}},{"name":"field","in":"path","description":"Sensitive field path, such as url or env.API_TOKEN","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveMcpConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"401":{"description":"Unauthorized"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"MCP server or field not found"},"500":{"description":"Configuration read or audit failed"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/monitors":{"get":{"tags":["Status Page"],"summary":"List monitors for a project","operationId":"list_monitors","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved monitors","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MonitorResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Status Page"],"summary":"Create a new monitor","operationId":"create_monitor","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMonitorRequest"}}},"required":true},"responses":{"201":{"description":"Monitor created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/observe/events":{"get":{"tags":["Observability"],"summary":"List a merged page of observability events for a project.","description":"Each row carries everything the side panel needs to render — no\nfollow-up fetch is required for the common case. Heavy fields\n(stacktraces, headers, span attributes) are truncated server-side and\nexpose a `*_truncated` flag; clients fetch the full row from the\n`/full` endpoint only when the user explicitly clicks \"Show full\".","operationId":"observability_list_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"kinds","in":"query","description":"Comma-separated kinds: `log,request,span,error,revenue`. Empty or\nmissing returns every kind.","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","description":"Inclusive lower bound on event timestamp (ISO 8601, `Z` suffix).","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Inclusive upper bound on event timestamp.","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"deployment_id","in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"search","in":"query","description":"Free-text substring matched against per-kind summary fields\n(request path / error class / revenue event_type).","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size (default 50, max 200).","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"hide_bots","in":"query","description":"When `true`, exclude bot/crawler request rows. When `false`, only\ninclude bot rows. Omitted means \"include everything\" (default).\nOnly affects the `Request` kind.","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Merged event page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsResponse"}}}},"400":{"description":"Invalid filter (kinds, time range, …)","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"text/plain":{"schema":{"type":"string"}}}},"403":{"description":"Insufficient permissions","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/observe/events/{kind}/{event_id}/full":{"get":{"tags":["Observability"],"summary":"Fetch the un-truncated form of one event by `(kind, id)`. Side panel\n\"Show full\" action calls this — the list response carries truncated\npreviews + a `*_truncated` flag to let the UI decide whether to fetch.","operationId":"observability_full_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"kind","in":"path","description":"Event kind discriminator","required":true,"schema":{"$ref":"#/components/schemas/EventKind"}},{"name":"event_id","in":"path","description":"Per-kind identity: request_id for requests, `{trace_id}:{span_id}` for spans, serial id for errors/revenue","required":true,"schema":{"type":"string"}},{"name":"ts","in":"query","description":"The row's event timestamp as returned by the list endpoint. Optional,\nbut strongly recommended: it bounds the lookup to the storage\npartitions/chunks around that instant instead of scanning the whole\nretention window.","required":false,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Full row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FullEvent"}}}},"401":{"description":"Unauthorized","content":{"text/plain":{"schema":{"type":"string"}}}},"403":{"description":"Insufficient permissions","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Event not found in project","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/releases/{release}/source-files":{"get":{"tags":["source-maps"],"summary":"List uploaded source files for a release (metadata only).","operationId":"list_source_files","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of source files","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceFileListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["source-maps"],"summary":"Upload a raw source file for a release (native symbolication).","description":"Accepts a multipart form with:\n- `file`: the source file bytes (required)\n- `file_path`: the path of the file as it appears in stack frames (required;\n derived from the uploaded filename if omitted). Normalized with the `~`\n prefix convention, matching source-map storage.\n\nRequires the project's `error_source_context_enabled` toggle to be on.\nUpserts on (project, release, file_path).","operationId":"upload_source_file","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Source file uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceFileResponse"}}}},"400":{"description":"Missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Source context disabled for project"},"413":{"description":"Source file too large"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["source-maps"],"summary":"Delete all uploaded source files for a release.","operationId":"delete_release_source_files","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Source files deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/releases/{release}/source-maps":{"get":{"tags":["source-maps"],"summary":"List all source maps for a specific release","operationId":"list_source_maps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of source maps","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceMapListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["source-maps"],"summary":"Upload a source map for a release.","description":"Accepts a multipart form with:\n- `file`: The .map file (required)\n- `file_path`: The URL path of the minified file as it appears in stack traces (required).\n Uses the ~ prefix convention (e.g., \"~/assets/main.js\").\n If a full URL is provided, it will be normalized automatically.\n- `dist`: Optional distribution identifier\n\nIf a source map already exists for the same (project, release, file_path), it is replaced.","operationId":"upload_source_map","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Source map uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceMapResponse"}}}},"400":{"description":"Invalid source map or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"413":{"description":"Source map too large"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["source-maps"],"summary":"Delete all source maps for a specific release","operationId":"delete_release_source_maps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Source maps deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/events":{"get":{"tags":["Revenue"],"summary":"Recent ingested events for the activity feed.","operationId":"revenue_recent_events","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecentEventResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations":{"get":{"tags":["Revenue"],"summary":"List revenue integrations for a project.","operationId":"revenue_list_integrations","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IntegrationResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Revenue"],"summary":"Create a new revenue integration. Response contains the generated\nwebhook path that the user must paste into their provider's dashboard.","operationId":"revenue_create_integration","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIntegrationBody"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"409":{"description":"Already connected"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}":{"delete":{"tags":["Revenue"],"summary":"Delete a revenue integration (permanent — use rotate_token to refresh\ncredentials without breaking history).","operationId":"revenue_delete_integration","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/config":{"post":{"tags":["Revenue"],"summary":"Replace the typed provider config on an integration. Passing `null`\nclears the config back to the accept-everything default. The config's\nprovider tag must match the integration's provider.","operationId":"revenue_update_config","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConfigBody"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Integration not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/import/invoices":{"post":{"tags":["Revenue"],"summary":"Import a Stripe invoices CSV export. Each paid invoice becomes an\n`invoice.paid` event so historical MRR/charge totals populate the\ntimeseries. Ingestion is idempotent: re-uploading the same file is a\nno-op.","operationId":"revenue_import_invoices_csv","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOutcomeResponse"}}}},"400":{"description":"Malformed CSV or wrong provider"},"404":{"description":"Integration not found"},"413":{"description":"CSV too large"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/import/subscriptions":{"post":{"tags":["Revenue"],"summary":"Import a Stripe subscriptions CSV export. Use this to backfill MRR /\nactive subscriptions when migrating from Stripe without providing\nAPI keys. Webhooks remain the source of truth for live updates —\nCSV rows never overwrite newer webhook state.","operationId":"revenue_import_subscriptions_csv","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOutcomeResponse"}}}},"400":{"description":"Malformed CSV or wrong provider"},"404":{"description":"Integration not found"},"413":{"description":"CSV too large"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/rotate-token":{"post":{"tags":["Revenue"],"summary":"Rotate the webhook path token. Returns the new integration state —\nthe user must paste the new URL into their provider's dashboard.","operationId":"revenue_rotate_token","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/update-secret":{"post":{"tags":["Revenue"],"summary":"Replace the stored signing secret without rotating the webhook URL.\nUse this after rotating the secret in the provider's dashboard.","operationId":"revenue_update_secret","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSecretBody"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Integration not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/customers":{"get":{"tags":["Revenue"],"summary":"New + churned customers per bucket.","operationId":"revenue_metrics_customers","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomerMovementResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/mrr":{"get":{"tags":["Revenue"],"summary":"Bucketed MRR timeseries for the revenue chart.","operationId":"revenue_metrics_mrr","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MrrBucketResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/summary":{"get":{"tags":["Revenue"],"summary":"Current MRR / ARR / churn / ARPU for a project, in one currency.","operationId":"revenue_metrics_summary","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsSummaryResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/secrets":{"get":{"tags":["Secrets"],"summary":"List project secrets (metadata only — values never returned).","operationId":"listProjectSecrets","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment filter","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of secrets (metadata only, no values)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Secrets"],"summary":"Create a new secret. The value is encrypted before storage and will be\nmounted as a file at `/run/secrets/` on the next deployment.\nThe plaintext value is NOT returned — the response carries only metadata.","operationId":"createProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectSecretRequest"}}},"required":true},"responses":{"201":{"description":"Secret created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}},"400":{"description":"Invalid key or value too large"},"409":{"description":"Key already exists in project"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/secrets/{secret_id}":{"put":{"tags":["Secrets"],"summary":"Update a project secret. Value rotation requires a redeploy to take effect —\nrunning containers keep their currently-mounted values until the next\ndeployment.","operationId":"updateProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"secret_id","in":"path","description":"Secret ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectSecretRequest"}}},"required":true},"responses":{"200":{"description":"Secret updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}},"400":{"description":"Value too large"},"404":{"description":"Secret not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Secrets"],"summary":"Delete a project secret. Running containers keep their mounted secret files\nuntil they are redeployed.","operationId":"deleteProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"secret_id","in":"path","description":"Secret ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Secret deleted"},"404":{"description":"Secret not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/settings":{"post":{"tags":["Projects"],"summary":"Update project settings","operationId":"update_project_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Project settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills":{"get":{"tags":["Agents"],"operationId":"list_skills","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSkillsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSkillRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/upload":{"post":{"tags":["Agents"],"summary":"Upload a skill with an archive (tar.gz) — project-scoped.","operationId":"upload_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/{slug}":{"get":{"tags":["Agents"],"operationId":"get_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSkillRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Skill deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/{slug}/archive":{"get":{"tags":["Agents"],"summary":"Download a skill's archive (tar.gz) — project-scoped.","operationId":"download_skill_archive","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill archive tar.gz","content":{"application/gzip":{}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found or has no archive"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/source-map-releases":{"get":{"tags":["source-maps"],"summary":"List all releases that have source maps for a project","operationId":"list_releases","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of releases","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/source-maps/{source_map_id}":{"delete":{"tags":["source-maps"],"summary":"Delete a specific source map by ID","operationId":"delete_source_map","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"source_map_id","in":"path","description":"Source map ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Source map deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Source map not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/static-bundles":{"get":{"tags":["Static Bundles"],"summary":"List static bundles for a project","operationId":"list_static_bundles","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of static bundles","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedStaticBundlesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/static-bundles/{bundle_id}":{"get":{"tags":["Static Bundles"],"summary":"Get details of a specific static bundle","operationId":"get_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"bundle_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Bundle details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaticBundleResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Static Bundles"],"summary":"Delete a static bundle","operationId":"delete_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"bundle_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Bundle deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/status":{"get":{"tags":["Status Page"],"summary":"Get status page overview","operationId":"get_status_overview","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved status overview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageOverview"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/unique-counts":{"get":{"tags":["Events"],"summary":"Get unique counts over time frame","operationId":"get_unique_counts","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric to count: 'sessions' (unique sessions), 'visitors' (unique visitors), 'returning_visitors' (visitors seen before the range), or 'page_views' (total page views) (default: 'sessions')","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UniqueCountsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/upload/static":{"post":{"tags":["Static Bundles"],"summary":"Upload a static bundle for later deployment","description":"Uploads a tar.gz or zip file containing static assets. The bundle can be\ndeployed later using the deploy/static endpoint.","operationId":"upload_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"201":{"description":"Bundle uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaticBundleResponse"}}}},"400":{"description":"Invalid request or unsupported format"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"413":{"description":"Bundle too large"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans":{"get":{"tags":["Vulnerability Scans"],"operationId":"list_project_scans","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of vulnerability scans","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScanResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Vulnerability Scans"],"operationId":"trigger_scan","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerScanRequest"}}},"required":true},"responses":{"202":{"description":"Scan triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerScanResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans/environments":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_latest_scans_per_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest scans per environment for current deployments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScanResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans/latest":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_latest_scan","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest scan for project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"No scans found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks":{"get":{"tags":["Webhooks"],"summary":"List all webhooks for a project","operationId":"list_webhooks","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of webhooks","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Webhooks"],"summary":"Create a new webhook","operationId":"create_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequestBody"}}},"required":true},"responses":{"201":{"description":"Webhook created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}":{"get":{"tags":["Webhooks"],"summary":"Get a specific webhook","operationId":"get_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Webhook details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Webhooks"],"summary":"Update a webhook","operationId":"update_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequestBody"}}},"required":true},"responses":{"200":{"description":"Webhook updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","operationId":"delete_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Webhook deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries":{"get":{"tags":["Webhook Deliveries"],"summary":"List webhook deliveries","operationId":"list_deliveries","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Number of deliveries to return (default: 50)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of deliveries","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries/{delivery_id}":{"get":{"tags":["Webhook Deliveries"],"summary":"Get a specific webhook delivery by ID","operationId":"get_delivery","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"delivery_id","in":"path","description":"Delivery ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Delivery details including full payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Delivery not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries/{delivery_id}/retry":{"post":{"tags":["Webhook Deliveries"],"summary":"Retry a failed delivery","operationId":"retry_delivery","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"delivery_id","in":"path","description":"Delivery ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Delivery retried","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Delivery not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/workflows/dry-run":{"post":{"tags":["Workflows"],"operationId":"workflow_dry_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDryRunRequest"}}},"required":true},"responses":{"202":{"description":"Ephemeral run created and queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Validation error (bad YAML, oversized payload, capped limits exceeded)"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/proxy-logs":{"get":{"tags":["Proxy Logs"],"summary":"Get proxy logs with optional filters and pagination","operationId":"get_proxy_logs","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"session_id","in":"query","description":"Filter by session ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"visitor_id","in":"query","description":"Filter by visitor ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering (ISO 8601 format).\n\n**Defaults to 1 hour before `end_date` (or before now) when omitted.**\nThe listing is always time-bounded: an unbounded query would have to\nconsider the entire retention window — 100M+ rows on a busy deployment —\nto return a single page. Pass an explicit `start_date` to widen the\nwindow, up to the configured retention horizon.\n\nThe maximum span between `start_date` and `end_date` is 7 days when\n`project_id` is omitted, or 30 days when a single `project_id` is set —\na project-scoped query is bounded by that project's own row count\nrather than the whole deployment's. A wider request is rejected with a\n400 naming the applicable cap.","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"end_date","in":"query","description":"End date for filtering (ISO 8601 format). Defaults to now.","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"method","in":"query","description":"Filter by HTTP method (GET, POST, etc.)","required":false,"schema":{"type":["string","null"]}},{"name":"host","in":"query","description":"Filter by host header","required":false,"schema":{"type":["string","null"]}},{"name":"path","in":"query","description":"Filter by path (supports partial match)","required":false,"schema":{"type":["string","null"]}},{"name":"client_ip","in":"query","description":"Filter by client IP address","required":false,"schema":{"type":["string","null"]}},{"name":"status_code","in":"query","description":"Filter by HTTP status code","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"response_time_min","in":"query","description":"Filter by minimum response time in ms","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"response_time_max","in":"query","description":"Filter by maximum response time in ms","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"routing_status","in":"query","description":"Filter by routing status (routed, no_project, error, pending)","required":false,"schema":{"type":["string","null"]}},{"name":"request_source","in":"query","description":"Filter by request source (proxy, api, console, cli)","required":false,"schema":{"type":["string","null"]}},{"name":"is_system_request","in":"query","description":"Filter by system request flag","required":false,"schema":{"type":["boolean","null"]}},{"name":"user_agent","in":"query","description":"Filter by user agent string (partial match)","required":false,"schema":{"type":["string","null"]}},{"name":"browser","in":"query","description":"Filter by browser name","required":false,"schema":{"type":["string","null"]}},{"name":"operating_system","in":"query","description":"Filter by operating system","required":false,"schema":{"type":["string","null"]}},{"name":"device_type","in":"query","description":"Filter by device type (mobile, desktop, tablet)","required":false,"schema":{"type":["string","null"]}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":["boolean","null"]}},{"name":"exclude_bots","in":"query","description":"When `true`, exclude rows flagged as bots while KEEPING rows whose\n`is_bot` is NULL (older rows without detection metadata). This is the\ntri-state complement of `is_bot=false`, which matches only rows\nexplicitly detected as non-bots. `false`/omitted is a no-op.","required":false,"schema":{"type":["boolean","null"]}},{"name":"bot_name","in":"query","description":"Filter by bot name","required":false,"schema":{"type":["string","null"]}},{"name":"ai_provider","in":"query","description":"Filter by AI provider (e.g. `OpenAI`, `Anthropic`, `Perplexity`). Matches\nthe canonical provider returned by the AI agent detector.","required":false,"schema":{"type":["string","null"]}},{"name":"ai_agent","in":"query","description":"Filter by AI agent name (e.g. `GPTBot`, `ChatGPT-User`). Equivalent to\nfiltering `bot_name` against a known AI taxonomy.","required":false,"schema":{"type":["string","null"]}},{"name":"is_ai_agent","in":"query","description":"When `true`, only return requests classified as known AI agents\n(regardless of provider/agent). Mutually compatible with the above.","required":false,"schema":{"type":["boolean","null"]}},{"name":"request_size_min","in":"query","description":"Filter by minimum request size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"request_size_max","in":"query","description":"Filter by maximum request size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"response_size_min","in":"query","description":"Filter by minimum response size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"response_size_max","in":"query","description":"Filter by maximum response size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"cache_status","in":"query","description":"Filter by cache status","required":false,"schema":{"type":["string","null"]}},{"name":"container_id","in":"query","description":"Filter by container ID","required":false,"schema":{"type":["string","null"]}},{"name":"upstream_host","in":"query","description":"Filter by upstream host","required":false,"schema":{"type":["string","null"]}},{"name":"has_error","in":"query","description":"Filter by presence of error message","required":false,"schema":{"type":["boolean","null"]}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"sort_by","in":"query","description":"Sort by field (default: timestamp)","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","description":"Sort order (asc or desc, default: desc)","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of proxy logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogsPaginatedResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/ai-agents/known":{"get":{"tags":["Proxy Logs"],"summary":"List every AI agent the detector knows how to classify.","description":"Returned in the same order as the internal taxonomy so the UI can use it as\na stable dropdown.","operationId":"list_known_ai_agents","responses":{"200":{"description":"Known AI agents","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnownAiAgentsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/request/{request_id}":{"get":{"tags":["Proxy Logs"],"summary":"Get a proxy log by request ID (for tracing)","operationId":"get_proxy_log_by_request_id","parameters":[{"name":"request_id","in":"path","description":"Request ID from pingora","required":true,"schema":{"type":"string"}},{"name":"timestamp","in":"query","description":"Event time of the log row (ISO 8601). When provided, the lookup is\nbounded to the hypertable chunks around this instant instead of\nscanning (and decompressing) the whole retention window. The list\nendpoint already returns this value per row — always pass it when\nnavigating from a list.","required":false,"schema":{"type":["string","null"],"format":"date-time"}}],"responses":{"200":{"description":"Proxy log found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Proxy log not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agent-pages":{"get":{"tags":["Proxy Logs"],"summary":"Get the top pages accessed by a specific AI agent over a time window.","description":"Returns page paths ranked by request count, scoped to a single canonical\nagent name (e.g. `ChatGPT-User`). Use `GET /proxy-logs/ai-agents/known` to\nlist all valid agent names. Unknown agent names return an empty items array.","operationId":"get_ai_agent_pages","parameters":[{"name":"agent","in":"query","description":"Canonical agent name to filter by (e.g. `ChatGPT-User`, `ClaudeBot`).\nMust be a name returned by `GET /proxy-logs/ai-agents/known`.","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Filter by project ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"Pages breakdown for the requested agent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentPagesResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agents":{"get":{"tags":["Proxy Logs"],"summary":"Get the per-AI-agent breakdown for a project over a time window.","operationId":"get_ai_agent_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI agent breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agents/timeline":{"get":{"tags":["Proxy Logs"],"summary":"Time-bucketed AI-agent request volume, split by provider or agent.","description":"Powers the \"AI agents over time\" stacked chart. Same data source as the AI\nagent breakdown (request logs), just bucketed.","operationId":"get_ai_agent_timeline","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"group_by","in":"query","description":"Grouping dimension: `provider` (default) or `agent`.","required":false,"schema":{"type":["string","null"]},"example":"provider"},{"name":"bucket","in":"query","description":"Bucket interval override (e.g. `1 hour`, `1 day`). Auto-selected from the\nwindow width when omitted.","required":false,"schema":{"type":["string","null"]},"example":"1 hour"}],"responses":{"200":{"description":"AI agent timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentTimelineResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-pages":{"get":{"tags":["Proxy Logs"],"summary":"Get the top pages crawled by AI agents over a time window.","operationId":"get_ai_page_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI page breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiPageBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-status":{"get":{"tags":["Proxy Logs"],"summary":"HTTP status-class breakdown for AI-agent traffic — are bots being served\n(2xx) or hitting broken/blocked pages (4xx/5xx)?","operationId":"get_ai_status_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI status breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiStatusBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/projects-health":{"get":{"tags":["Proxy Logs"],"summary":"Get health summaries for multiple projects (last 1 hour)","operationId":"get_projects_health","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Optional start time (ISO 8601). Defaults to `end_time - 1h`.","required":false,"schema":{"type":["string","null"]},"example":"2025-10-23T00:00:00Z"},{"name":"end_time","in":"query","description":"Optional end time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2025-10-23T23:59:59Z"},{"name":"is_bot","in":"query","description":"Filter by bot detection. Pass `false` to exclude bots, `true` for bots only.","required":false,"schema":{"type":["boolean","null"]}}],"responses":{"200":{"description":"Health summaries per project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectsHealthResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/time-buckets":{"get":{"tags":["Proxy Logs"],"summary":"Get time-bucketed statistics with optional filters","operationId":"get_time_bucket_stats","parameters":[{"name":"start_time","in":"query","description":"Start time (ISO 8601 format)","required":true,"schema":{"type":"string"},"example":"2025-10-23T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601 format)","required":true,"schema":{"type":"string"},"example":"2025-10-23T23:59:59Z"},{"name":"bucket_interval","in":"query","description":"Bucket interval (e.g., \"1 hour\", \"1 day\", \"5 minutes\")","required":false,"schema":{"type":"string"}},{"name":"method","in":"query","description":"Filter by HTTP method","required":false,"schema":{"type":"string"}},{"name":"client_ip","in":"query","description":"Filter by client IP","required":false,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"host","in":"query","description":"Filter by host","required":false,"schema":{"type":"string"}},{"name":"status_code","in":"query","description":"Filter by status code","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"status_code_class","in":"query","description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")","required":false,"schema":{"type":"string"}},{"name":"routing_status","in":"query","description":"Filter by routing status","required":false,"schema":{"type":"string"}},{"name":"request_source","in":"query","description":"Filter by request source","required":false,"schema":{"type":"string"}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":"boolean"}},{"name":"device_type","in":"query","description":"Filter by device type","required":false,"schema":{"type":"string"}},{"name":"has_project","in":"query","description":"When true, only count requests that matched a project\n(project_id IS NOT NULL). Makes chart totals line up with the\nper-project health cards.","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Time-bucketed statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBucketStatsResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/today":{"get":{"tags":["Proxy Logs"],"summary":"Get today's request count with optional filters","operationId":"get_today_stats","parameters":[{"name":"method","in":"query","description":"Filter by HTTP method","required":false,"schema":{"type":["string","null"]}},{"name":"client_ip","in":"query","description":"Filter by client IP","required":false,"schema":{"type":["string","null"]}},{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"host","in":"query","description":"Filter by host","required":false,"schema":{"type":["string","null"]}},{"name":"status_code","in":"query","description":"Filter by status code","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"status_code_class","in":"query","description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")","required":false,"schema":{"type":["string","null"]}},{"name":"routing_status","in":"query","description":"Filter by routing status","required":false,"schema":{"type":["string","null"]}},{"name":"request_source","in":"query","description":"Filter by request source","required":false,"schema":{"type":["string","null"]}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":["boolean","null"]}},{"name":"device_type","in":"query","description":"Filter by device type","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Today's request count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TodayStatsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/{id}":{"get":{"tags":["Proxy Logs"],"summary":"Get a single proxy log by ID","operationId":"get_proxy_log_by_id","parameters":[{"name":"id","in":"path","description":"Proxy log ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"timestamp","in":"query","description":"Event time of the log row (ISO 8601). When provided, the lookup is\nbounded to the hypertable chunks around this instant instead of\nscanning (and decompressing) the whole retention window. The list\nendpoint already returns this value per row — always pass it when\nnavigating from a list.","required":false,"schema":{"type":["string","null"],"format":"date-time"}}],"responses":{"200":{"description":"Proxy log found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Proxy log not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/repositories":{"get":{"tags":["Git Providers"],"summary":"List synced repositories with advanced filtering","description":"Lists repositories that have been synced to the database with filtering options.\nThis provides fast access to repository metadata with filtering by connection, search, and other criteria.","operationId":"list_synced_repositories","parameters":[{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, watchers, size, issues)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}},{"name":"git_provider_connection_id","in":"query","description":"Filter by git provider connection ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of synced repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}":{"get":{"tags":["Git Providers"],"summary":"Get repository by owner and name from any connection","operationId":"get_repository_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Optional specific connection ID to search","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Repository found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}/all":{"get":{"tags":["Git Providers"],"summary":"Get all repositories with same owner/name from all git providers","operationId":"get_all_repositories_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repositories found from all providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RepositoryResponse"}}}}},"404":{"description":"No repositories found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}/preset":{"get":{"tags":["Git Providers"],"summary":"Get repository preset by owner and name","operationId":"get_repository_preset_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"branch","in":"query","description":"Git branch to check (defaults to repository's default branch)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository preset calculated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryPresetResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{repo}/branches":{"get":{"tags":["Repositories"],"summary":"Get repository branches","operationId":"get_repository_branches","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Git provider connection ID (required when multiple connections have the same repo)","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{repo}/tags":{"get":{"tags":["Repositories"],"summary":"Get repository tags","operationId":"get_repository_tags","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Git provider connection ID (required when multiple connections have the same repo)","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Fresh tag lookup rate limit exceeded"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{repository_id}/preset/live":{"get":{"tags":["Git Providers"],"operationId":"get_repository_preset_live","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"branch","in":"query","description":"Git branch to check (defaults to repository's default branch)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository presets calculated successfully - includes root preset and projects in subdirectories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryPresetResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"The git provider rejected the stored credential - the connection must be re-authorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}":{"get":{"tags":["Git Providers"],"summary":"Get repository by ID","operationId":"get_repository_by_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Repository found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/branches":{"get":{"tags":["Repositories"],"summary":"Get repository branches by repository ID","operationId":"get_branches_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/commits":{"get":{"tags":["Repositories"],"summary":"List recent commits for a repository branch","operationId":"list_commits_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"branch","in":"query","description":"Branch name to list commits for","required":true,"schema":{"type":"string"}},{"name":"per_page","in":"query","description":"Number of commits to return (default: 20, max: 100)","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}}],"responses":{"200":{"description":"List of commits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/commits/{commit_sha}":{"get":{"tags":["Repositories"],"summary":"Check if a commit exists in a repository","operationId":"check_commit_exists","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"commit_sha","in":"path","description":"Commit SHA to check","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Commit existence check result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitExistsResponse"}}}},"400":{"description":"Invalid commit SHA"},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Commit lookup rate limit exceeded"},"500":{"description":"Internal server error"},"502":{"description":"Git provider request failed"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/tags":{"get":{"tags":["Repositories"],"summary":"Get repository tags by repository ID","operationId":"get_tags_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Fresh tag lookup rate limit exceeded"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/restore-runs/{id}":{"get":{"tags":["Restore"],"operationId":"get_restore_run","parameters":[{"name":"id","in":"path","description":"Restore run id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Restore run progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreRunView"}}}},"404":{"description":"Restore run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/events":{"get":{"tags":["Revenue"],"summary":"Org-wide revenue events across every project. Powers the revenue\ntransactions page. Supports filtering by project, date range, and\nevent type.","operationId":"revenue_global_events","parameters":[{"name":"project_id","in":"query","description":"Filter to a single project","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"from","in":"query","description":"Lower bound (inclusive), ISO-8601","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"Upper bound (inclusive), ISO-8601","required":false,"schema":{"type":"string"}},{"name":"event_types","in":"query","description":"Comma-separated event types (e.g. `invoice.paid,charge.succeeded`)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max rows, default 100, max 500","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GlobalRecentEventResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/metrics/global-mrr":{"get":{"tags":["Revenue"],"summary":"Org-wide MRR total, summed across every project in the install.\nPowers the single-number MRR card on the main dashboard.","operationId":"revenue_metrics_global_mrr","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalMrrResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/metrics/global-summary":{"get":{"tags":["Revenue"],"summary":"Org-wide revenue summary: MRR, paid cash (30d + all-time), refunds,\nactive subscriptions/customers, and transaction count. Powers the\nheader on the Revenue transactions page.","operationId":"revenue_metrics_global_summary","parameters":[{"name":"currency","in":"query","description":"ISO-4217 currency code, default USD","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalRevenueSummaryResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/providers":{"get":{"tags":["Revenue"],"summary":"List registered providers (what the UI needs to render the \"Connect\"\ndropdown + its wizard instructions).","operationId":"revenue_list_providers","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderDescriptor"}}}}}},"security":[{"bearer_auth":[]}]}},"/session-replays":{"get":{"tags":["Analytics"],"summary":"Get session replays for a project","operationId":"get_project_session_replays","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Session replays retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetProjectSessionReplaysResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/sessions/{session_id}/events":{"get":{"tags":["Events"],"summary":"Get events for a specific session","operationId":"get_session_events","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsSessionEventsResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings":{"get":{"tags":["Settings"],"summary":"Get application settings","operationId":"get_settings","responses":{"200":{"description":"Application settings with masked sensitive fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppSettingsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Settings"],"summary":"Update application settings","operationId":"update_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppSettings"}}},"required":true},"responses":{"200":{"description":"Settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"400":{"description":"Bad request - invalid settings"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/agent-token":{"post":{"tags":["Agents"],"summary":"Save an encrypted AI provider token for use in sandbox containers.","operationId":"save_agent_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAgentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token encrypted and persisted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAgentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Encryption or database error"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers":{"get":{"tags":["Agents"],"summary":"List the AI provider catalog. Includes per-provider \"is a credential\nconfigured?\" so the settings UI can render configured/not-configured\nbadges without leaking the encrypted credential.","operationId":"list_ai_providers","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderCatalogResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}":{"patch":{"tags":["Agents"],"summary":"Update provider-scoped settings without touching the saved credential.\nToday that means just `default_model`; future per-provider settings\n(base URL overrides, request headers, etc.) can land here too without\nchanging the shape of `save_credential`.","operationId":"update_ai_provider","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiProviderRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiProviderResponse"}}}},"400":{"description":"Unknown provider"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}/activate":{"post":{"tags":["Agents"],"summary":"Activate a provider as the platform-wide default. Refuses to activate a\nprovider that doesn't have a credential saved yet — the UI enforces the\nsame rule on the button, but we re-check server-side so a stale tab\ncan't bypass it.","operationId":"activate_ai_provider","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivateProviderResponse"}}}},"400":{"description":"Provider not configured"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}/credential":{"post":{"tags":["Agents"],"summary":"Save (or replace) a provider's credential. The credential is encrypted\nwith `EncryptionService` and stored inside\n`agent_sandbox.providers[provider_id].credentials_encrypted`.","description":"The plaintext shape depends on the flavor's `credential_format`:\n - `ApiKey` / `OauthToken`: the key/token string.\n - `ConfigFile`: the full file body (e.g. OpenCode's `auth.json`).","operationId":"save_ai_provider_credential","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveCredentialRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveCredentialResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/disk-status":{"get":{"tags":["Settings"],"summary":"Get current disk usage for the control-plane server","description":"Returns live disk usage for the monitored path along with any disks that\nmeet or exceed the configured alert threshold. Read-only — does not send\nnotifications. Used by the dashboard to surface a low-disk-space warning.","operationId":"get_disk_status","responses":{"200":{"description":"Current disk usage and threshold alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiskSpaceCheckResult"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/enrollment-tokens":{"get":{"tags":["Settings"],"summary":"List currently-valid node enrollment tokens (hashes elided).","operationId":"list_enrollment_tokens","responses":{"200":{"description":"Active enrollment tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollmentTokenListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Settings"],"summary":"Mint a short-lived, single-use node enrollment token.","operationId":"mint_enrollment_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintEnrollmentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Enrollment token minted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintEnrollmentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/enrollment-tokens/{id}":{"delete":{"tags":["Settings"],"summary":"Revoke a node enrollment token by id.","operationId":"revoke_enrollment_token","parameters":[{"name":"id","in":"path","description":"Enrollment token id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Enrollment token revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Enrollment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token":{"delete":{"tags":["Settings"],"summary":"Revoke the current join token","description":"Removes the stored join token hash, allowing any node to register\n(if no other authentication is in place).","operationId":"revoke_join_token","responses":{"200":{"description":"Join token revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token/generate":{"post":{"tags":["Settings"],"summary":"Generate a new join token for multi-node cluster registration","description":"Creates a random 32-byte hex token, stores the SHA-256 hash in settings,\nand returns the plaintext exactly once. If a token already exists, it is replaced.","operationId":"generate_join_token","responses":{"200":{"description":"Join token generated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateJoinTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token/status":{"get":{"tags":["Settings"],"summary":"Check whether a join token is currently configured","operationId":"get_join_token_status","responses":{"200":{"description":"Join token status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinTokenStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers":{"get":{"tags":["Agents"],"operationId":"list_global_mcps","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMcpsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_global_mcp","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMcpRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers/{slug}":{"get":{"tags":["Agents"],"operationId":"get_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMcpRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"MCP server deleted"},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers/{slug}/config/{field}":{"get":{"tags":["Agents"],"operationId":"reveal_global_mcp_config","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}},{"name":"field","in":"path","description":"Sensitive field path, such as url or env.API_TOKEN","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveMcpConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"401":{"description":"Unauthorized"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"MCP server or field not found"},"500":{"description":"Configuration read or audit failed"}},"security":[{"bearer_auth":[]}]}},"/settings/routes/refresh":{"post":{"tags":["Settings"],"summary":"Manually refresh the proxy route table","description":"Reloads all routes from the database into the in-memory proxy cache.\nUseful as a workaround when routes are out of sync.","operationId":"refresh_route_table","responses":{"200":{"description":"Route table refreshed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteRefreshResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/sandbox-rebuild":{"post":{"tags":["Agents"],"operationId":"rebuild_sandbox_image","responses":{"200":{"description":"Server-Sent Events stream of rebuild progress; final event `{\"type\":\"done\",\"success\":bool,...}`","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/sandbox-status":{"get":{"tags":["Agents"],"operationId":"get_global_sandbox_status","responses":{"200":{"description":"Global sandbox readiness for the settings page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/secrets":{"get":{"tags":["Secrets"],"operationId":"list_secrets","responses":{"200":{"description":"List of global agent secrets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSecretsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Secrets"],"operationId":"upsert_secret","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertSecretRequest"}}},"required":true},"responses":{"201":{"description":"Secret created/updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/secrets/{name}":{"delete":{"tags":["Secrets"],"operationId":"delete_secret","parameters":[{"name":"name","in":"path","description":"Secret name","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Secret deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Secret not found"}},"security":[{"bearer_auth":[]}]}},"/settings/skills":{"get":{"tags":["Agents"],"operationId":"list_global_skills","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSkillsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_global_skill","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSkillRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/upload":{"post":{"tags":["Agents"],"summary":"Upload a skill with an archive (tar.gz) — global.","operationId":"upload_global_skill","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/{slug}":{"get":{"tags":["Agents"],"operationId":"get_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSkillRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Skill deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/{slug}/archive":{"get":{"tags":["Agents"],"summary":"Download a skill's archive (tar.gz) — global.","operationId":"download_global_skill_archive","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill archive tar.gz","content":{"application/gzip":{}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found or has no archive"}},"security":[{"bearer_auth":[]}]}},"/settings/update-status":{"get":{"tags":["Settings"],"summary":"Report whether a newer temps release is available for this install.","operationId":"get_update_status","responses":{"200":{"description":"Release update status for this install","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/templates":{"get":{"tags":["Templates"],"summary":"List all available templates","description":"Returns a list of all public templates, optionally filtered by tag or featured status.","operationId":"list_project_templates","parameters":[{"name":"tag","in":"query","description":"Filter templates by tag","required":false,"schema":{"type":"string"}},{"name":"featured","in":"query","description":"Only return featured templates","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of templates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTemplatesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/templates/tags":{"get":{"tags":["Templates"],"summary":"List all available template tags","description":"Returns a list of all unique tags used by public templates.","operationId":"list_project_template_tags","responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTagsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/templates/{slug}":{"get":{"tags":["Templates"],"summary":"Get a specific template by slug","description":"Returns detailed information about a single template.","operationId":"get_project_template","parameters":[{"name":"slug","in":"path","description":"Template slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Template not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/user/me":{"get":{"tags":["Authentication"],"operationId":"get_current_user","responses":{"200":{"description":"Successfully retrieved user information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/users":{"get":{"tags":["Users"],"operationId":"list_users","parameters":[{"name":"include_deleted","in":"query","description":"Include deleted users in the response","required":true,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List all users with their roles","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}}},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Users"],"summary":"Create a new user with roles","operationId":"create_user","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRequest"}}},"required":true},"responses":{"201":{"description":"User created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me":{"patch":{"tags":["Users"],"summary":"Update current user's information","operationId":"update_self","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSelfRequest"}}},"required":true},"responses":{"200":{"description":"User updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa":{"delete":{"tags":["Users"],"operationId":"disable_mfa","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableMfaRequest"}}},"required":true},"responses":{"204":{"description":"MFA disabled"},"400":{"description":"Invalid verification code"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa/setup":{"post":{"tags":["Users"],"operationId":"setup_mfa","responses":{"200":{"description":"MFA setup data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaSetupResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa/verify":{"post":{"tags":["Users"],"operationId":"verify_and_enable_mfa","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyMfaRequest"}}},"required":true},"responses":{"204":{"description":"MFA verified and enabled"},"400":{"description":"Invalid code"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/password":{"post":{"tags":["Users"],"operationId":"change_password_self","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"204":{"description":"Password updated"},"400":{"description":"Validation error (weak password, same as current, MFA missing)"},"401":{"description":"Current password incorrect or MFA code invalid"},"403":{"description":"Account has no password set (SSO only)"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}":{"delete":{"tags":["Users"],"summary":"Delete a user","operationId":"delete_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"User deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Cannot delete yourself or non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Users"],"summary":"Update user information (admin only)","operationId":"update_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequest"}}},"required":true},"responses":{"200":{"description":"User updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/restore":{"post":{"tags":["Users"],"operationId":"restore_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"User restored successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"User is not deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/roles":{"post":{"tags":["Users"],"operationId":"assign_role","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignRoleRequest"}}},"required":true},"responses":{"200":{"description":"Role assigned successfully"},"400":{"description":"Invalid role type"},"401":{"description":"Unauthorized"},"403":{"description":"Admin role required or self-modification forbidden"},"404":{"description":"User or role not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/roles/{role_type}":{"delete":{"tags":["Users"],"operationId":"remove_role","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"role_type","in":"path","description":"Role type to remove","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Role removed successfully"},"400":{"description":"Invalid role type"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Cannot modify own roles or non-admin attempt"},"404":{"description":"User or role not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes":{"get":{"tags":["Sandboxes"],"operationId":"list_sandboxes","parameters":[{"name":"page","in":"query","description":"Page (1-indexed)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default 20, max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List sandboxes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSandboxesResponse"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Sandboxes"],"operationId":"create_sandbox","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSandboxBody"}}},"required":true},"responses":{"201":{"description":"Sandbox created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/rootfs":{"get":{"tags":["Sandboxes"],"summary":"Inspect rootfs storage: the Firecracker digest-keyed cache (with which\nsandboxes reference each entry) and per-VM disks. Empty on Docker-only\nhosts. Admin/read scope — this exposes host storage layout.","operationId":"rootfs_report","responses":{"200":{"description":"Rootfs storage report"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/rootfs/gc":{"post":{"tags":["Sandboxes"],"summary":"Reclaim rootfs cache entries not backing any live sandbox. Idempotent;\nsafe to call any time (live VMs hold their own per-VM disks).","operationId":"rootfs_gc","responses":{"200":{"description":"Reclaimed cache entries"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}":{"get":{"tags":["Sandboxes"],"operationId":"get_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd":{"post":{"tags":["Sandboxes"],"summary":"Run a command inside the sandbox (`@vercel/sandbox`-compatible).","description":"`wait=false` (default) returns `{ command: {..., exitCode: null} }`\nimmediately once the background task is spawned.\n\n`wait=true` streams `application/x-ndjson`: the first line is the\nrunning envelope, the second is the finished envelope with `exitCode`.","operationId":"cmd","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdBody"}}},"required":true},"responses":{"200":{"description":"Command started (wait=false) or finished (wait=true)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd/{cmd_id}":{"get":{"tags":["Sandboxes"],"operationId":"get_cmd","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Command snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd/{cmd_id}/logs":{"get":{"tags":["Sandboxes"],"summary":"Stream a command's stdout/stderr as `application/x-ndjson`\n(`@vercel/sandbox`-compatible). Each line is either\n`{stream:\"stdout\"|\"stderr\", data:\"...\"}` or\n`{stream:\"error\", data:{code, message}}`.","operationId":"cmd_logs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"NDJSON stream of log events"},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/destroy":{"post":{"tags":["Sandboxes"],"operationId":"destroy_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Sandbox destroyed (alias for `/stop` with an explicit verb)"},"404":{"description":"Not found"},"409":{"description":"Sandbox belongs to an active agent run — stop the run instead"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/domain":{"get":{"tags":["Sandboxes"],"operationId":"domain","parameters":[{"name":"port","in":"query","description":"Port inside the sandbox (1..=65535)","required":true,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Preview URL for the port","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxDomainResponse"}}}},"400":{"description":"Invalid port"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/events":{"get":{"tags":["Sandboxes"],"summary":"The operations timeline for a sandbox (lifecycle events only — never\nshell/exec activity), newest first.","operationId":"list_events","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Operations timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxEventsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/exec":{"post":{"tags":["Sandboxes"],"operationId":"exec","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecBody"}}},"required":true},"responses":{"200":{"description":"Command finished (non-zero exit is NOT an error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/exec-detached":{"post":{"tags":["Sandboxes"],"operationId":"exec_detached","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecBody"}}},"required":true},"responses":{"202":{"description":"Command accepted; poll /jobs/{job_id}","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecDetachedResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/extend-timeout":{"post":{"tags":["Sandboxes"],"operationId":"extend_timeout","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtendTimeoutBody"}}},"required":true},"responses":{"200":{"description":"Timeout extended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/mkdir":{"post":{"tags":["Sandboxes"],"operationId":"mkdir","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MkdirBody"}}},"required":true},"responses":{"204":{"description":"Directory created (or already existed)"},"400":{"description":"Validation error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/read":{"get":{"tags":["Sandboxes"],"operationId":"read_file","parameters":[{"name":"path","in":"query","description":"Absolute file path inside the sandbox","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File contents (base64)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadFileResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Sandbox or file not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/stat":{"get":{"tags":["Sandboxes"],"operationId":"stat_path","parameters":[{"name":"path","in":"query","description":"Absolute path inside the sandbox","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Stat info (exists=false when missing — not an error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatResponse"}}}},"400":{"description":"Validation error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/write":{"post":{"tags":["Sandboxes"],"summary":"Write a file into the sandbox. Accepts two body shapes — the SDK\npicks one based on `Content-Type`:","description":"- **`application/json`** (temps-native): `{path, contents_b64, mode}`\n — one file, base64-encoded.\n- **`application/gzip`** (`@vercel/sandbox`): a gzipped tarball of\n one-or-more entries, with the target extract dir carried in the\n `x-cwd` header. The SDK's `writeFile` and `writeFiles` both post\n here; they differ only in how many entries the tarball contains.\n\nWhy merge them on one route: the SDK is hardcoded to\n`POST /fs/write`, so splitting tar uploads onto a separate path would\nforce us to break SDK compat. Instead we dispatch on Content-Type,\npreserve JSON for native callers, and add tar for SDK callers.","operationId":"write_file","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFileBody"}}},"required":true},"responses":{"204":{"description":"File(s) written"},"400":{"description":"Validation error or invalid base64"},"404":{"description":"Sandbox not found"},"415":{"description":"Unsupported Content-Type (expected application/json or application/gzip)"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/write-batch":{"post":{"tags":["Sandboxes"],"summary":"Batch-write multiple files in a single request. Mirrors\n`@vercel/sandbox` `writeFiles()`. Semantics are fail-fast: if any\nfile errors, previously-written entries are left in place and the\nerror describes which file broke.","operationId":"write_files","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFilesBody"}}},"required":true},"responses":{"200":{"description":"All files written","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFilesResponse"}}}},"400":{"description":"Validation error or invalid base64"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs":{"get":{"tags":["Sandboxes"],"operationId":"list_jobs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Detached jobs for this sandbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListJobsResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}":{"get":{"tags":["Sandboxes"],"operationId":"job_status","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusResponse"}}}},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}/kill":{"post":{"tags":["Sandboxes"],"summary":"Terminate a detached job. Aborts the server-side tracking task and\nsends SIGTERM (or SIGKILL if `force=true`) to any matching processes\ninside the sandbox container. Returns 204 on success; 404 if the\nsandbox or job is unknown.","operationId":"kill_job","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KillJobBody"}}},"required":true},"responses":{"204":{"description":"Job killed"},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}/logs":{"get":{"tags":["Sandboxes"],"summary":"SSE endpoint streaming each stdout/stderr line from a detached job\nas it's produced. Mirrors the `Command.logs()` async iterator shape\non `@vercel/sandbox` — events carry `{ stream, data }`.","description":"Late subscribers only see events produced after they connect. The\nJobState snapshot (`GET /jobs/{job_id}`) covers the history.\n\nA \"done\" sentinel event fires when the broadcast channel closes\n(the exec task has exited and dropped the sender), signalling\ncallers they can stop reading.","operationId":"job_logs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"SSE stream of log events"},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/pause":{"post":{"tags":["Sandboxes"],"operationId":"pause_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox paused (container stopped, state preserved)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is in an incompatible state (e.g. already destroyed)"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/preview-password":{"put":{"tags":["Sandboxes"],"operationId":"set_preview_password","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPreviewPasswordBody"}}},"required":true},"responses":{"200":{"description":"Preview password set or rotated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPreviewPasswordResponse"}}}},"400":{"description":"Password too short or too long"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Sandboxes"],"operationId":"clear_preview_password","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Preview password removed (sandbox is now URL-only protected)"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/resize":{"post":{"tags":["Sandboxes"],"summary":"Grow a Firecracker sandbox's root disk. Offline resize — the VM reboots\n(filesystem/data persist) rather than resizing fully live.","operationId":"resize_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResizeSandboxBody"}}},"required":true},"responses":{"200":{"description":"Resized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Invalid size or unsupported backend"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/restart":{"post":{"tags":["Sandboxes"],"operationId":"restart_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox container restarted in place","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is stopped (use /resume) or already destroyed"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/resume":{"post":{"tags":["Sandboxes"],"operationId":"resume_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox resumed; expires_at refreshed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is not in a resumable state"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/source":{"post":{"tags":["Sandboxes"],"operationId":"source_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceBody"}}},"required":true},"responses":{"200":{"description":"Source content seeded into the sandbox work dir","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error (embedded creds, conflicting fields, etc.)"},"404":{"description":"Sandbox not found"},"409":{"description":"Sandbox is not running"},"500":{"description":"Source seed failed inside sandbox"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/stop":{"post":{"tags":["Sandboxes"],"operationId":"stop_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Sandbox stopped and destroyed"},"404":{"description":"Not found"},"409":{"description":"Sandbox belongs to an active agent run — stop the run instead"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/{cmd_id}/kill":{"post":{"tags":["Sandboxes"],"summary":"Kill a running command (`@vercel/sandbox`-compatible). The SDK\ncalls `POST /v1/sandboxes/{id}/{cmdId}/kill` — note the path has the\ncommand ID directly under the sandbox, NOT under `/jobs/` or `/cmd/`.","operationId":"cmd_kill","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdKillBody"}}}},"responses":{"200":{"description":"Command killed; returns final snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays":{"get":{"tags":["Analytics"],"summary":"Get session replays for a visitor","operationId":"get_visitor_sessions","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Session replays retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVisitorSessionsResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}":{"get":{"tags":["Analytics"],"summary":"Get session replay data with visitor info (without events)","operationId":"get_session_replay","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Session replay retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSessionReplayResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Analytics"],"summary":"Delete a session replay","operationId":"delete_session_replay","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Session replay deleted successfully"},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}/duration":{"put":{"tags":["Analytics"],"summary":"Update session duration","operationId":"update_session_duration","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionDurationRequest"}}},"required":true},"responses":{"200":{"description":"Session duration updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionDurationResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}/events":{"get":{"tags":["Analytics"],"summary":"Get session replay events (with session and visitor metadata)","operationId":"get_session_replay_events","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Session replay with events retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayWithEventsDto"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Analytics"],"summary":"Add events to an existing session","operationId":"add_events","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsRequest"}}},"required":true},"responses":{"200":{"description":"Events added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/vulnerability-scans/{scan_id}":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Scan details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Vulnerability Scans"],"operationId":"delete_scan","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Scan deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/vulnerability-scans/{scan_id}/vulnerabilities":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan_vulnerabilities","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"severity","in":"query","description":"Filter by severity (CRITICAL, HIGH, MEDIUM, LOW)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of vulnerabilities","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VulnerabilityResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/webhook-event-types":{"get":{"tags":["Webhooks"],"summary":"List available event types","operationId":"list_event_types","responses":{"200":{"description":"List of available event types","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTypeResponse"}}}}}}}},"/weekly-digest/trigger":{"post":{"tags":["Notification Preferences"],"summary":"Trigger weekly digest generation manually","operationId":"trigger_weekly_digest","responses":{"200":{"description":"Weekly digest triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerDigestResponse"}}}},"500":{"description":"Failed to generate digest"}},"security":[{"bearer_auth":[]}]}},"/x/plugins":{"get":{"tags":["External Plugins"],"summary":"List all running external plugins and their manifests.","description":"Requires only a valid session/token (no specific permission) since the\nmanifest drives sidebar navigation rendering for every authenticated\nuser, not just admins.","operationId":"list_external_plugins","responses":{"200":{"description":"List of all running external plugins","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PluginManifest"}}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/x/plugins/reload":{"post":{"tags":["External Plugins"],"summary":"Reload all external plugins.","description":"Stops all running plugin processes, re-scans the plugins directory,\nstarts any discovered binaries, and hot-swaps the proxy router so new\nand removed plugins take effect immediately without a server restart.\n\nRequires `SystemAdmin` permission.","operationId":"reload_plugins","responses":{"200":{"description":"Plugins reloaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReloadResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/{project_id}/envelope/":{"post":{"tags":["sentry-ingestor"],"summary":"Ingest a Sentry envelope (binary payload)","operationId":"ingest_sentry_envelope","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"Sentry envelope as binary data","content":{"application/octet-stream":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Envelope ingested"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"413":{"description":"Request body too large (exceeds 2 MiB)"}}}},"/{project_id}/store/":{"post":{"tags":["sentry-ingestor"],"summary":"Ingest a Sentry event (JSON payload)","operationId":"ingest_sentry_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryEventRequest"}}},"required":true},"responses":{"200":{"description":"Event ingested","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryEventResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"413":{"description":"Request body too large (exceeds 2 MiB)"}}}},"audit/logs":{"get":{"tags":["Audit Logs"],"summary":"List audit logs with optional filtering","operationId":"list_audit_logs","parameters":[{"name":"operation_type","in":"query","description":"Filter logs by operation type (omit for all)","required":false,"schema":{"type":"string"},"example":"user.login"},{"name":"user_id","in":"query","description":"Filter logs by user ID (omit for all users)","required":false,"schema":{"type":"integer","format":"int32"},"example":1},{"name":"from","in":"query","description":"Start timestamp (milliseconds since epoch)","required":false,"schema":{"type":"string","format":"date-time"},"example":1},{"name":"to","in":"query","description":"End timestamp (milliseconds since epoch)","required":false,"schema":{"type":"string","format":"date-time"},"example":1},{"name":"limit","in":"query","description":"Maximum number of logs to return","required":false,"schema":{"type":"integer","format":"int32"},"example":100},{"name":"offset","in":"query","description":"Number of logs to skip","required":false,"schema":{"type":"integer","format":"int32"},"example":0}],"responses":{"200":{"description":"List of audit logs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuditLogResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"api_key":[]}]}},"audit/logs/{id}":{"get":{"tags":["Audit Logs"],"summary":"Get a specific audit log entry by ID","operationId":"get_audit_log","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Audit log details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Audit log not found"},"500":{"description":"Internal server error"}},"security":[{"api_key":[]}]}}},"components":{"schemas":{"AcmeOrderResponse":{"type":"object","required":["id","order_url","domain_id","email","status","identifiers","created_at","updated_at"],"properties":{"authorizations":{},"certificate_url":{"type":["string","null"]},"challenge_validation":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeValidationStatus","description":"Live challenge validation status fetched from Let's Encrypt"}]},"created_at":{"type":"integer","format":"int64"},"domain_id":{"type":"integer","format":"int32"},"email":{"type":"string"},"error":{"type":["string","null"]},"error_type":{"type":["string","null"]},"expires_at":{"type":["integer","null"],"format":"int64"},"finalize_url":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"identifiers":{},"order_url":{"type":"string"},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"ActivateProviderResponse":{"type":"object","required":["default_provider"],"properties":{"default_provider":{"type":"string"}}},"ActiveVisitor":{"type":"object","required":["session_id","session_start","last_activity","page_count","event_count","duration_seconds","is_active"],"properties":{"current_page":{"type":["string","null"]},"duration_seconds":{"type":"integer","format":"int64"},"event_count":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_activity":{"type":"string"},"page_count":{"type":"integer","format":"int32"},"session_id":{"type":"string"},"session_start":{"type":"string"},"visitor_id":{"type":["string","null"]}}},"ActiveVisitorsQuery":{"type":"object","properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"}}},"ActiveVisitorsResponse":{"type":"object","required":["active_visitors","window_minutes"],"properties":{"active_visitors":{"type":"integer","format":"int64"},"window_minutes":{"type":"integer","format":"int32"}}},"ActivityDay":{"type":"object","description":"Daily activity count for a single day","required":["date","count","level"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of deployments on this day"},"date":{"type":"string","description":"Date in YYYY-MM-DD format","example":"2024-06-15"},"level":{"type":"integer","format":"int32","description":"Intensity level (0-4) for visualization\n0: No activity, 1: Low (1-2), 2: Medium (3-5), 3: High (6-10), 4: Very High (11+)","example":2}}},"ActivityEvent":{"type":"object","description":"A single activity event for the real-time activity feed","required":["id","timestamp","event_type","page_path","is_crawler"],"properties":{"browser":{"type":["string","null"],"description":"Browser"},"city":{"type":["string","null"],"description":"Visitor's city (from ip_geolocations)"},"country":{"type":["string","null"],"description":"Visitor's country (from ip_geolocations)"},"country_code":{"type":["string","null"],"description":"Visitor's country code (from ip_geolocations)"},"device_type":{"type":["string","null"],"description":"Device type"},"event_name":{"type":["string","null"],"description":"Event name (for custom events)"},"event_type":{"type":"string","description":"Event type: \"page_view\", \"custom\", etc."},"id":{"type":"integer","format":"int64","description":"Event ID"},"is_crawler":{"type":"boolean","description":"Whether this event was from a crawler"},"latitude":{"type":["number","null"],"format":"double","description":"Latitude"},"longitude":{"type":["number","null"],"format":"double","description":"Longitude"},"operating_system":{"type":["string","null"],"description":"Operating system"},"page_path":{"type":"string","description":"Page path where the event happened"},"page_title":{"type":["string","null"],"description":"Page title"},"referrer":{"type":["string","null"],"description":"Referrer"},"timestamp":{"type":"string","format":"date-time","description":"When the event occurred"},"visitor_id":{"type":["integer","null"],"format":"int32","description":"Visitor numeric ID"}}},"ActivityGraphQuery":{"type":"object","description":"Query parameters for activity graph endpoint","properties":{"days":{"type":"integer","format":"int32","description":"Number of days to include (default: 365 for last year)"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID to filter activity"},"project_id":{"type":["integer","null"],"format":"int32","description":"Optional project ID to filter activity"}}},"ActivityGraphResponse":{"type":"object","description":"Response for activity graph showing daily deployment activity","required":["days","total_count","start_date","end_date"],"properties":{"days":{"type":"array","items":{"$ref":"#/components/schemas/ActivityDay"},"description":"Array of daily activity counts"},"end_date":{"type":"string","description":"Date range end (YYYY-MM-DD)","example":"2024-12-31"},"start_date":{"type":"string","description":"Date range start (YYYY-MM-DD)","example":"2024-01-01"},"total_count":{"type":"integer","format":"int64","description":"Total count of activities across all days"}}},"AddClusterMemberRequest":{"type":"object","description":"Request body for adding a single member to a running cluster.","required":["role"],"properties":{"node_id":{"type":["integer","null"],"format":"int32","description":"Target worker node ID. Omit or null to run on the control plane."},"role":{"type":"string","description":"Member role. Currently only `replica` is accepted at runtime —\nmonitor is a singleton, primary is elected by pg_auto_failover.","example":"replica"}}},"AddContextRequest":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"AddEnvironmentDomainRequest":{"type":"object","required":["domain","is_primary"],"properties":{"domain":{"type":"string"},"is_primary":{"type":"boolean"}}},"AddEventsRequest":{"type":"object","required":["events"],"properties":{"events":{"type":"string"}}},"AddEventsResponse":{"type":"object","required":["event_count","message"],"properties":{"event_count":{"type":"integer","minimum":0},"message":{"type":"string"}}},"AddManagedDomainApiRequest":{"type":"object","description":"Request to add a managed domain","required":["domain"],"properties":{"auto_manage":{"type":"boolean"},"domain":{"type":"string","example":"example.com"},"generated_hostname_mode":{"type":["string","null"],"description":"Generated hostname layout: `\"standard\"` (default) or `\"flat\"`."},"sync_generated_records":{"type":"boolean","description":"Opt in to reconciling generated hostnames into this domain's DNS zone."}}},"AdminGateResponse":{"type":"object","required":["allowed_ips","allowed_hosts","trust_forwarded_for","source","editable"],"properties":{"allowed_hosts":{"type":"array","items":{"type":"string"},"description":"`Host` header values allowed. Empty = any host."},"allowed_ips":{"type":"array","items":{"type":"string"},"description":"IPs / CIDRs allowed to reach the admin listener. Empty = any source."},"editable":{"type":"boolean","description":"True when the config is writable through this API. False when env\nvars are dictating the active config."},"source":{"$ref":"#/components/schemas/AdminGateSource","description":"Where the active config came from."},"trust_forwarded_for":{"type":"boolean","description":"When true, the gate trusts `X-Forwarded-For` from loopback peers."}}},"AdminGateSource":{"type":"string","description":"Where the active gate configuration came from. Env-supplied configs are\nfrozen at the process level — the UI shows them read-only and refuses to\npersist DB writes. DB-supplied configs are editable at runtime.","enum":["default","db","env"]},"AgentConfigResponse":{"type":"object","description":"Response DTO for a single agent — masks the encrypted API key.","required":["id","project_id","slug","name","source","enabled","trigger_config","ai_provider","api_key_set","max_turns","timeout_seconds","daily_budget_cents","cooldown_minutes","branch_prefix","deliverable","created_at","updated_at"],"properties":{"ai_model":{"type":["string","null"],"description":"Preferred model for the CLI (e.g. \"sonnet\", \"gpt-5-codex\"). `None` means default."},"ai_provider":{"type":"string"},"ai_provider_key_id":{"type":["integer","null"],"format":"int32"},"api_key_set":{"type":"boolean","description":"`true` if an API key is set; `false` otherwise."},"branch_prefix":{"type":"string"},"config_repo_branch":{"type":["string","null"],"description":"Branch of the config repo to use."},"config_repo_url":{"type":["string","null"],"description":"Private config repo containing .claude/ directory (skills, MCP, plugins)."},"cooldown_minutes":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"daily_budget_cents":{"type":"integer","format":"int32"},"deliverable":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"max_turns":{"type":"integer","format":"int32"},"mcp_servers_config":{"description":"MCP servers config (Claude Code settings.json mcpServers format).\nCredential-bearing legacy inline values are write-only and appear as\n`***`. Omit this field on update to preserve their stored values."},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"prompt":{"type":["string","null"]},"sandbox_enabled":{"type":["boolean","null"],"description":"None = use global sandbox setting, true = force on, false = force off"},"skills_config":{"description":"Skills config as JSON array."},"slug":{"type":"string"},"source":{"type":"string"},"timeout_seconds":{"type":"integer","format":"int32"},"tools_config":{"description":"Tools config as JSON array. Legacy custom-tool webhook URLs and headers\nare write-only and appear as `***`. Omit this field on update to\npreserve their stored values."},"trigger_config":{},"updated_at":{"type":"string"},"webhook_token":{"type":["string","null"],"description":"Secret token for the `X-Webhook-Token` header. Shown once when created,\nmasked with `***` prefix in subsequent reads."},"webhook_url":{"type":["string","null"],"description":"Public webhook URL for triggering this agent externally.\nOnly set when `on: { webhook: true }` is configured.\nUsage: `POST {webhook_url}` with header `X-Webhook-Token: {webhook_token}`"}}},"AgentRunLogResponse":{"type":"object","required":["id","run_id","level","message","created_at"],"properties":{"created_at":{"type":"string"},"id":{"type":"integer","format":"int64"},"level":{"type":"string"},"message":{"type":"string"},"metadata":{},"run_id":{"type":"integer","format":"int32"}}},"AgentRunResponse":{"type":"object","required":["id","project_id","source","trigger_type","status","tokens_input","tokens_output","estimated_cost_cents","files_changed","created_at","sandbox_enabled"],"properties":{"agent_name":{"type":["string","null"],"description":"Name of the agent that created this run, if available."},"agent_slug":{"type":["string","null"],"description":"Slug of the agent that created this run, if available."},"ai_model":{"type":["string","null"]},"ai_output":{"type":["string","null"]},"ai_provider":{"type":["string","null"],"description":"AI provider slug that executed this run (e.g. claude_cli, codex_cli, opencode)."},"ai_reasoning":{"type":["string","null"]},"ai_session_id":{"type":["string","null"],"description":"Claude CLI session UUID for resuming conversations via `--resume`."},"analysis":{"type":["string","null"],"description":"Report / analysis text produced by the agent (used for report/notification deliverables)."},"branch_name":{"type":["string","null"]},"commit_sha":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"config_id":{"type":["integer","null"],"format":"int32","description":"Optional. NULL for ephemeral CLI runs (`source = \"cli_ephemeral\"`) and\nhistorical autofixer runs that pre-date the agent_id column."},"created_at":{"type":"string"},"ephemeral_yaml":{"type":["string","null"],"description":"Full WorkflowYamlConfig as YAML text. Populated only when\n`source = \"cli_ephemeral\"`. Used by the web UI to show a \"View YAML\"\nmodal so the user can see exactly what the executor ran."},"error_message":{"type":["string","null"]},"estimated_cost_cents":{"type":"integer","format":"int32"},"files_changed":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"phase":{"type":["string","null"],"description":"Autofixer phase: \"analyzing\", \"analyzed\", \"fixing\", \"fix_ready\", \"no_fix\",\n\"pr_created\", or NULL for non-autofixer runs."},"pr_number":{"type":["integer","null"],"format":"int32"},"pr_url":{"type":["string","null"]},"preview_url":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"prompt_text":{"type":["string","null"],"description":"Final assembled prompt the AI CLI actually saw (trigger context block +\nYAML prompt, with error-group fields interpolated). Captured once per\nrun. `None` for pre-migration rows."},"run_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AutofixRunConfig","description":"Per-run AI options the user chose when starting an autofixer run\n(provider, model, max_turns, branch). NULL for generic agent runs\nand historical rows. Used to prefill the retry dialog."}]},"sandbox_enabled":{"type":"boolean","description":"Legacy field — all runs now execute in a sandbox. Kept for\nbackwards-compatible JSON shape; always `true`."},"source":{"type":"string","description":"`committed` (the run's config lives in `project_agents`) or\n`cli_ephemeral` (the config was uploaded via the CLI for a one-off\ndry run; see `ephemeral_yaml`)."},"started_at":{"type":["string","null"]},"status":{"type":"string"},"tokens_input":{"type":"integer","format":"int32"},"tokens_output":{"type":"integer","format":"int32"},"trigger_source_id":{"type":["integer","null"],"format":"int32"},"trigger_source_type":{"type":["string","null"]},"trigger_type":{"type":"string"},"user_context":{"type":["string","null"],"description":"User-provided context for this run (e.g. webhook payload, manual instructions)."}}},"AgentRunWithLogsResponse":{"type":"object","required":["run","logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunLogResponse"}},"run":{"$ref":"#/components/schemas/AgentRunResponse"}}},"AgentSandboxSettings":{"type":"object","description":"Global agent sandbox settings. Controls whether agent runs are isolated\ninside Docker containers by default. Individual agents can override this.","properties":{"api_key_encrypted":{"type":["string","null"],"description":"DEPRECATED: use `providers[default_provider].credentials_encrypted` instead.","default":null},"auth_type":{"type":"string","description":"DEPRECATED: use `providers[default_provider].auth_type` instead.","default":"subscription"},"cpu_limit":{"type":"number","format":"double","description":"CPU limit in cores for sandbox containers","default":4.0,"example":4.0},"custom_image":{"type":"string","description":"Custom Docker image (only used when runtime is \"custom\").\nMust have git and claude CLI installed.","default":"","example":""},"default_provider":{"type":"string","description":"Default AI provider for agents: \"claude_cli\", \"opencode\", or \"codex_cli\".\nWorkspaces always use this provider — no per-session override.","default":"claude_cli","example":"claude_cli"},"enabled":{"type":"boolean","description":"Sandbox is always enabled — the executor refuses to run any agent\noutside a sandboxed container. Field is retained so existing settings\nrows still deserialize, but it is ignored at runtime.","default":true},"memory_limit_mb":{"type":"integer","format":"int64","description":"Memory limit in MB for sandbox containers","default":8192,"example":8192,"minimum":0},"network_mode":{"type":"string","description":"Network access level: \"full\" (unrestricted), \"restricted\" (Temps network only), \"none\" (no network)","default":"full","example":"full"},"providers":{"type":"object","description":"Per-provider auth + config. Keyed by provider id (e.g. `claude_cli`,\n`codex_cli`, `opencode`). Adding a new provider only requires a new\ncatalog entry on the Rust side — the JSON column stays migration-free.","default":{},"additionalProperties":{"$ref":"#/components/schemas/ProviderConfig"},"propertyNames":{"type":"string"}},"runtime":{"type":"string","description":"Runtime preset: \"node\", \"bun\", \"python\", \"rust\", \"go\", \"full\", or \"custom\"","default":"node","example":"node"},"sandbox_backend":{"type":["string","null"],"description":"Default isolation backend for sandboxes: \"docker\" (default) or\n\"firecracker\" (ADR-029; requires `temps firecracker setup`). Only\nconsulted when the Firecracker backend probes available — otherwise\nDocker is used regardless.","default":null,"example":"docker"}}},"AgentSandboxSettingsMasked":{"type":"object","description":"Agent sandbox settings with masked per-provider credentials.\nEach provider entry reports only whether a credential is saved, not\nthe encrypted blob itself. Non-sensitive fields (auth_type, default_model,\nextra) are passed through so the UI can render provider-specific state.","required":["default_provider","providers","api_key_saved","auth_type","enabled","runtime","custom_image","cpu_limit","memory_limit_mb","network_mode","sandbox_backend"],"properties":{"api_key_saved":{"type":"boolean"},"auth_type":{"type":"string"},"cpu_limit":{"type":"number","format":"double"},"custom_image":{"type":"string"},"default_provider":{"type":"string"},"enabled":{"type":"boolean"},"memory_limit_mb":{"type":"integer","format":"int64","minimum":0},"network_mode":{"type":"string"},"providers":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ProviderConfigMasked"},"propertyNames":{"type":"string"}},"runtime":{"type":"string"},"sandbox_backend":{"type":"string"}}},"AggregatedBucketItem":{"type":"object","required":["timestamp","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"AggregatedBucketsQuery":{"type":"object","description":"Query parameters for aggregated metrics by time bucket","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events, sessions, or visitors"},"bucket_size":{"type":"string","description":"Time bucket size: \"1 hour\", \"1 day\", \"1 week\", etc. (default: \"1 hour\")"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"AggregatedBucketsResponse":{"type":"object","required":["bucket_size","aggregation_level","items","total"],"properties":{"aggregation_level":{"type":"string"},"bucket_size":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AggregatedBucketItem"}},"total":{"type":"integer","format":"int64"}}},"AggregationLevel":{"type":"string","enum":["events","sessions","visitors"]},"AggregationTemporality":{"type":"string","description":"The aggregation temporality of a Sum/Histogram/ExponentialHistogram metric.\n\nMirrors OTel's `AggregationTemporality` proto enum: whether reported values\nare cumulative since the start of the series (Cumulative) or only the delta\nsince the previous report (Delta).","enum":["unspecified","delta","cumulative"]},"AiAgentBreakdownResponse":{"type":"object","description":"Response wrapping the AI agent breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentBreakdownRow"}},"start_time":{"type":"string"}}},"AiAgentBreakdownRow":{"type":"object","description":"One row in the AI-agent analytics breakdown. `agent` is the canonical\ncrawler name (e.g. `GPTBot`, `Claude-User`), `provider` is the vendor used\nfor grouping + logos. The UI mirrors the browsers card and ranks by\n`request_count`.","required":["provider","agent","purpose","request_count","unique_ips"],"properties":{"agent":{"type":"string"},"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"provider":{"type":"string"},"purpose":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"unique_ips":{"type":"integer","format":"int64"}}},"AiAgentDescriptor":{"type":"object","description":"Static descriptor for one entry in the known-AI-agents taxonomy.","required":["provider","agent","purpose"],"properties":{"agent":{"type":"string"},"provider":{"type":"string"},"purpose":{"type":"string"}}},"AiAgentPageRow":{"type":"object","description":"One row in the pages-by-agent breakdown. Returned by\n[`ProxyLogService::get_ai_agent_pages`] for a single named agent.\n`unique_ips` counts distinct client IPs that hit this path via that agent\n(same definition as the per-agent unique-IPs in [`AiAgentBreakdownRow`]).","required":["path","request_count","unique_ips"],"properties":{"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"path":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"unique_ips":{"type":"integer","format":"int64"}}},"AiAgentPagesResponse":{"type":"object","description":"Response wrapping the per-agent pages breakdown rows.","required":["agent","items","start_time","end_time"],"properties":{"agent":{"type":"string","description":"The agent name this breakdown is scoped to."},"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentPageRow"}},"start_time":{"type":"string"}}},"AiAgentTimelineResponse":{"type":"object","description":"Response wrapping the AI agent timeline rows.","required":["items","start_time","end_time","bucket","group_by"],"properties":{"bucket":{"type":"string","description":"Bucket interval used for the buckets (so the UI can label the x-axis).","example":"1 hour"},"end_time":{"type":"string"},"group_by":{"type":"string","description":"Echoes the grouping dimension actually applied.","example":"provider"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentTimelineRow"}},"start_time":{"type":"string"}}},"AiAgentTimelineRow":{"type":"object","description":"One point in the AI-agent timeline: the request count for a single\n(`bucket`, `key`) pair, where `key` is a provider or agent name depending on\nthe requested grouping. The UI pivots these into one stacked series per\n`key` across the shared bucket x-axis.","required":["bucket","key","request_count"],"properties":{"bucket":{"type":"string","description":"Bucket start in RFC3339 format.","example":"2026-05-29T12:00:00Z"},"key":{"type":"string","description":"Provider or agent name this count belongs to.","example":"OpenAI"},"request_count":{"type":"integer","format":"int64"}}},"AiConfigSettings":{"type":"object","description":"Global AI configuration settings. Controls the default config repo\ncontaining `.claude/` directory (skills, MCP servers, plugins) that\ngets overlaid into every agent sandbox.","properties":{"config_repo":{"type":"string","description":"Global config repo URL in \"owner/repo\" format (e.g. \"myorg/claude-config\").\nCloned at agent run time and overlaid into the sandbox's `.claude/` directory.","default":"","example":""},"config_repo_branch":{"type":"string","description":"Branch of the config repo to use.","default":"main","example":"main"}}},"AiPageBreakdownResponse":{"type":"object","description":"Response wrapping the AI page breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiPageBreakdownRow"}},"start_time":{"type":"string"}}},"AiPageBreakdownRow":{"type":"object","description":"One row in the AI-crawled-pages breakdown. `agent_count` is the number of\n*distinct* AI agents that hit this path, so the UI can show both how heavily\nand how broadly a page is being crawled.","required":["path","request_count","agent_count"],"properties":{"agent_count":{"type":"integer","format":"int64"},"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"path":{"type":"string"},"request_count":{"type":"integer","format":"int64"}}},"AiStatusBreakdownResponse":{"type":"object","description":"Response wrapping the AI status breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiStatusBreakdownRow"}},"start_time":{"type":"string"}}},"AiStatusBreakdownRow":{"type":"object","description":"One row in the AI-agent HTTP status breakdown: the request count for a\nstatus class (`2xx`/`3xx`/`4xx`/`5xx`/`other`) across crawler traffic.","required":["status_class","request_count"],"properties":{"request_count":{"type":"integer","format":"int64"},"status_class":{"type":"string","description":"Status class label.","example":"2xx"}}},"AlarmListResponse":{"type":"object","description":"Paginated list of alarms.","required":["items","total","page","page_size"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AlarmResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"AlarmResponse":{"type":"object","description":"Full alarm representation returned by list/summary endpoints.","required":["id","project_id","alarm_type","severity","status","title","fired_at","created_at","updated_at"],"properties":{"acknowledged_at":{"type":["string","null"],"description":"ISO-8601 UTC timestamp when the alarm was acknowledged, if any."},"acknowledged_by":{"type":["integer","null"],"format":"int32","description":"User ID who acknowledged the alarm, if any."},"alarm_type":{"type":"string"},"container_id":{"type":["integer","null"],"format":"int32"},"created_at":{"type":"string","description":"ISO-8601 UTC timestamp when the row was created."},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"fired_at":{"type":"string","description":"ISO-8601 UTC timestamp when the alarm fired."},"id":{"type":"integer","format":"int32"},"message":{"type":["string","null"]},"metadata":{"description":"Arbitrary JSON metadata attached by the alarm source."},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"description":"ISO-8601 UTC timestamp when the alarm was resolved, if any."},"service_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"status":{"type":"string"},"title":{"type":"string"},"updated_at":{"type":"string","description":"ISO-8601 UTC timestamp when the row was last updated."}}},"AlarmSummaryResponse":{"type":"object","description":"Re-export AlarmSummary for the OpenAPI schema.","required":["total_active","firing","acknowledged","critical","warning","by_type"],"properties":{"acknowledged":{"type":"integer","format":"int32","minimum":0},"by_type":{"type":"object","additionalProperties":{"type":"integer","format":"int32","minimum":0},"propertyNames":{"type":"string"}},"critical":{"type":"integer","format":"int32","minimum":0},"firing":{"type":"integer","format":"int32","minimum":0},"total_active":{"type":"integer","format":"int32","minimum":0},"warning":{"type":"integer","format":"int32","minimum":0}}},"AlertRuleResponse":{"type":"object","required":["id","project_id","name","trigger_type","trigger_config","notification_priority","cooldown_minutes","enabled","created_at","updated_at"],"properties":{"cooldown_minutes":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"enabled":{"type":"boolean"},"environment_filter":{"type":["integer","null"],"format":"int32"},"error_level_filter":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"notification_priority":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"trigger_config":{},"trigger_type":{"type":"string"},"updated_at":{"type":"string"}}},"AllocEntry":{"type":"object","description":"Wire-format allocation. `null` in the JSON when the node hasn't been\nallocated yet — workers should treat that as \"single-host mode, do\nnot bring up the overlay\".","required":["node_id","compute_cidr","bridge_address","underlay_address"],"properties":{"bridge_address":{"type":"string"},"compute_cidr":{"type":"string"},"node_id":{"type":"string","description":"Stable v5 UUID derived from the database node id."},"underlay_address":{"type":"string"}}},"AnalyticsSessionEventsResponse":{"type":"object","required":["session_id","events","total_events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEvent"}},"session_id":{"type":"string"},"total_events":{"type":"integer","minimum":0}}},"AnnotatedSpan":{"type":"object","description":"A single span annotated with the project that originally stored it.\nUsed in `UnifiedTrace` to let the UI colour-code spans by project.","required":["project_id","project_name","span"],"properties":{"project_id":{"type":"integer","format":"int32","description":"The project that stored this span (same as `span.project_id`)."},"project_name":{"type":"string","description":"Human-readable project name for waterfall colour-coding and legend."},"span":{"$ref":"#/components/schemas/SpanRecord","description":"Original span data verbatim from storage."}}},"AnomalyAlgorithm":{"type":"string","description":"Anomaly baseline algorithm. Adding one (e.g. a new robust variant) is a\ncode-only enum addition — no migration, since it lives inside the blob.","enum":["robust","basic","agile","ewma"]},"AnomalyParams":{"type":"object","description":"Seasonal anomaly-band detector parameters (stub — not yet evaluated).","properties":{"algorithm":{"$ref":"#/components/schemas/AnomalyAlgorithm","description":"Baseline model. `robust` is the default (seasonal, stable, flags level\nshifts); `ewma`/`agile` adopt level shifts; `basic` is non-seasonal."},"baseline_lookback_days":{"type":["integer","null"],"format":"int32","description":"How far back to build the baseline. `None` = an evaluator default."},"deviations":{"type":"number","format":"double","description":"Band width in robust standard deviations (Datadog's `bounds`)."},"direction":{"$ref":"#/components/schemas/Direction","description":"Which side(s) of the band a deviation must be on to count."},"pct_anomalous":{"type":"number","format":"double","description":"Fraction (0..=1) of points in the window that must be anomalous to fire."},"seasonality":{"$ref":"#/components/schemas/Seasonality","description":"Seasonality model for the baseline."}}},"AnomalyPreviewPointResponse":{"type":"object","required":["bucket","value","lower","upper","breaching"],"properties":{"breaching":{"type":"boolean"},"bucket":{"type":"string","example":"2025-10-12T12:15:47Z"},"lower":{"type":"number","format":"double","description":"Lower edge of the expected band at this point."},"upper":{"type":"number","format":"double","description":"Upper edge of the expected band at this point."},"value":{"type":"number","format":"double"}}},"AnomalyPreviewRequest":{"type":"object","required":["project_id","metric_name","aggregation","window_secs","detection_config"],"properties":{"aggregation":{"type":"string","description":"One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"Must be an `anomaly` detector — the band to backtest."},"end_time":{"type":["string","null"],"description":"RFC 3339; defaults to now.","example":"2025-10-12T12:15:47Z"},"metric_name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":["string","null"],"description":"RFC 3339; defaults to 7 days before `end_time`.","example":"2025-10-12T12:15:47Z"},"window_secs":{"type":"integer","format":"int32"}}},"AnomalyPreviewResponse":{"type":"object","required":["points","breach_count","baseline_samples","sufficient"],"properties":{"baseline_samples":{"type":"integer","format":"int64","description":"Baseline sample count (drives the `sufficient` flag)."},"breach_count":{"type":"integer","format":"int64","description":"How many points in the range would have fired."},"points":{"type":"array","items":{"$ref":"#/components/schemas/AnomalyPreviewPointResponse"}},"sufficient":{"type":"boolean","description":"Whether the baseline had enough history for a trustworthy band."}}},"ApiKeyListResponse":{"type":"object","required":["api_keys","total"],"properties":{"api_keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"ApiKeyResponse":{"type":"object","required":["id","name","key_prefix","role_type","is_active","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"key_prefix":{"type":"string"},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"role_type":{"type":"string"}}},"AppSettings":{"type":"object","description":"Application settings stored in the database\nAll fields have sensible defaults for easy onboarding","properties":{"agent_sandbox":{"oneOf":[{"$ref":"#/components/schemas/AgentSandboxSettings"}],"default":{"default_provider":"claude_cli","providers":{},"auth_type":"subscription","api_key_encrypted":null,"enabled":true,"runtime":"node","custom_image":"","cpu_limit":4.0,"memory_limit_mb":8192,"network_mode":"full","sandbox_backend":null}},"ai_config":{"oneOf":[{"$ref":"#/components/schemas/AiConfigSettings"}],"default":{"config_repo":"","config_repo_branch":"main"}},"build_limits":{"oneOf":[{"$ref":"#/components/schemas/BuildLimitsSettings","description":"Build-time resource limits applied on the control plane to prevent\n`docker build` from saturating host CPU/RAM. Worker nodes are\nintentionally NOT subject to these limits (each worker is dedicated\nhardware that already has its own per-host headroom)."}],"default":{"max_concurrent":2,"cpu_limit_cores":0.0,"memory_limit_mb":0}},"cluster_dns":{"oneOf":[{"$ref":"#/components/schemas/ClusterDnsSettings","description":"Cluster-DNS resolver settings (ADR-024, experimental beta). Off by\ndefault — see `ClusterDnsSettings` for the incident background and\ntrade-offs. Must be explicitly enabled by operators who need\n`*.temps.local` service-to-service resolution inside containers."}],"default":{"enabled":false}},"console_version":{"type":["string","null"],"description":"Binary version tag (e.g. \"v0.1.0\") of the *console* process\n(`temps serve`, role=all or role=console) that last started. Written\non console startup; read by the standalone `temps proxy` to detect\nversion skew during a rolling upgrade (ADR-017 Phase 3). `None` on\ninstalls that never ran a console build carrying this field.\n\nThis is informational state written by the binary itself — NOT an\noperator-tunable setting. It is intentionally absent from\n`AppSettingsResponse` and the PATCH path so an operator cannot\naccidentally overwrite the self-recorded value.","default":null},"container_logs":{"oneOf":[{"$ref":"#/components/schemas/ContainerLogSettings"}],"default":{"max_size":"50m","max_file":3,"service_max_size":"20m","service_max_file":3}},"disk_space_alert":{"oneOf":[{"$ref":"#/components/schemas/DiskSpaceAlertSettings"}],"default":{"enabled":true,"threshold_percent":80,"check_interval_seconds":300,"monitor_path":null}},"dns_provider":{"oneOf":[{"$ref":"#/components/schemas/DnsProviderSettings"}],"default":{"provider":"manual","cloudflare_api_key":null}},"docker_registry":{"oneOf":[{"$ref":"#/components/schemas/DockerRegistrySettings"}],"default":{"enabled":false,"registry_url":null,"username":null,"password":null,"tls_verify":true,"ca_certificate":null}},"edge_target":{"type":["string","null"],"description":"Public edge target that generated DNS records point at when a managed\ndomain opts into automatic record sync. An IPv4/IPv6 address produces an\n`A`/`AAAA` record; anything else is treated as a `CNAME` target. `None`\ndisables DNS record sync regardless of per-domain opt-in.","default":null},"external_url":{"type":["string","null"],"default":null},"insecure_tls":{"type":"boolean","description":"Skip TLS certificate verification on outbound HTTP clients built by the\nserver (deployer, agent, remote service client). Strictly opt-in for\noperators running self-signed control plane / worker certs on a trusted\ninternal network. Worker→control-plane traffic that traverses the public\ninternet must keep this `false` — otherwise a MitM steals the join token.","default":false},"internal_url":{"type":["string","null"],"description":"URL that service containers use to reach the Temps API from *inside*\nthe Docker network (OTLP metrics ingest, agent callbacks, etc.). On\nDocker Desktop this defaults to `http://host.docker.internal:`;\non Linux it requires the `host.docker.internal:host-gateway` host\nmapping (which Temps adds to provisioned containers). Distinct from\n`external_url`, which is the public-facing address.","default":null},"letsencrypt":{"oneOf":[{"$ref":"#/components/schemas/LetsEncryptSettings"}],"default":{"email":null,"environment":"production"}},"monitoring":{"oneOf":[{"$ref":"#/components/schemas/MonitoringSettings","description":"Metrics observability settings. Controls the MetricsStore backend,\nscrape interval, and tiered retention windows."}],"default":{"enabled":false,"store":"timescale_db","scrape_interval_secs":30,"retention_raw_days":7,"retention_hourly_days":90,"retention_daily_years":2,"clickhouse_url":null}},"multi_node":{"oneOf":[{"$ref":"#/components/schemas/MultiNodeSettings"}],"default":{"join_token_hash":null,"private_address":null,"legacy_shared_token_enabled":true,"cluster_ca_cert_pem":null,"cluster_ca_key_encrypted":null,"require_mtls":false,"node_cpu_alert_percent":90.0,"node_memory_alert_percent":90.0,"node_disk_alert_percent":90.0}},"observability_compression":{"oneOf":[{"$ref":"#/components/schemas/ObservabilityCompressionSettings","description":"TimescaleDB compression delays for immutable observability data.\nChanges are applied at runtime by the Settings API."}],"default":{"proxy_logs_after_hours":24,"otel_spans_after_hours":24}},"observability_retention":{"oneOf":[{"$ref":"#/components/schemas/ObservabilityRetentionSettings","description":"Retention windows for raw proxy and OpenTelemetry telemetry.\nTimescaleDB policies are updated at runtime by the Settings API."}],"default":{"proxy_logs_days":30,"otel_spans_days":90,"otel_logs_days":90,"otel_metrics_days":90}},"on_demand_tls":{"oneOf":[{"$ref":"#/components/schemas/OnDemandTlsSettings"}],"default":{"enabled":false,"zone":null,"max_concurrent":3,"hourly_cap":10,"deployment_url_mode":"http"}},"preview_domain":{"type":"string","default":"localho.st"},"preview_gateway":{"oneOf":[{"$ref":"#/components/schemas/PreviewGatewaySettings"}],"default":{"image":"ghcr.io/gotempsh/temps-preview-gateway:latest","host_port":8090,"auto_upgrade":true}},"rate_limiting":{"oneOf":[{"$ref":"#/components/schemas/RateLimitSettings"}],"default":{"enabled":false,"max_requests_per_minute":60,"max_requests_per_hour":1000,"whitelist_ips":[],"blacklist_ips":[]}},"require_mfa_for_admins":{"type":"boolean","description":"When `true`, any user holding the `Admin` role must have MFA enrolled\n(`users.mfa_enabled = true`) to complete a **password** login. Users\nwithout MFA enrolled are rejected with a typed error instructing them\nto enroll before retrying. This only gates the password-login path\n(`AuthService::login`) -- SSO/OIDC logins are handled by a separate\ncode path (`OidcService::resolve_user` + `oidc_handler`) and are\nintentionally unaffected, since federating identity to a\nproperly-hardened IdP is itself an acceptable alternative to local\nTOTP MFA. Modeled as a settings row (not an env var) per CLAUDE.md so\nan operator can flip it at runtime via the Settings API without\nrestarting the binary.","default":false},"screenshots":{"oneOf":[{"$ref":"#/components/schemas/ScreenshotSettings"}],"default":{"enabled":false,"provider":"local","url":""}},"security_headers":{"oneOf":[{"$ref":"#/components/schemas/SecurityHeadersSettings"}],"default":{"enabled":false,"preset":"moderate","content_security_policy":"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'","x_frame_options":"SAMEORIGIN","x_content_type_options":"nosniff","x_xss_protection":"1; mode=block","strict_transport_security":"max-age=31536000; includeSubDomains","referrer_policy":"strict-origin-when-cross-origin","permissions_policy":"geolocation=(), microphone=(), camera=()"}},"setup_complete":{"type":"boolean","description":"Set to `true` by `temps setup` (all modes) once initial configuration\nhas been applied. The web onboarding wizard reads this from the server\nand skips itself when true, preventing the \"Configure Base Domain\" wall\nfrom appearing on installs that were already configured via the CLI.","default":false}}},"AppSettingsResponse":{"type":"object","description":"Safe response for application settings that masks sensitive fields","required":["preview_domain","screenshots","letsencrypt","dns_provider","security_headers","rate_limiting","docker_registry","disk_space_alert","container_logs","agent_sandbox","ai_config","preview_gateway","multi_node","monitoring","observability_compression","observability_retention","effective_metrics_store","effective_observability_store","insecure_tls","setup_complete","require_mfa_for_admins","cluster_dns","build_limits"],"properties":{"agent_sandbox":{"$ref":"#/components/schemas/AgentSandboxSettingsMasked"},"ai_config":{"$ref":"#/components/schemas/AiConfigSettings"},"build_limits":{"$ref":"#/components/schemas/BuildLimitsSettings","description":"Build-time resource limits (control-plane only). No sensitive content,\npassed through as-is."},"cluster_dns":{"$ref":"#/components/schemas/ClusterDnsSettings","description":"Cluster-DNS resolver settings (ADR-024, experimental beta). No masking\nneeded — `enabled` is a plain bool with no sensitive content. Passed\nthrough as-is so the settings UI can read and toggle the flag."},"container_logs":{"$ref":"#/components/schemas/ContainerLogSettings"},"disk_space_alert":{"$ref":"#/components/schemas/DiskSpaceAlertSettings"},"dns_provider":{"$ref":"#/components/schemas/DnsProviderSettingsMasked"},"docker_registry":{"$ref":"#/components/schemas/DockerRegistrySettingsMasked"},"edge_target":{"type":["string","null"],"description":"Public edge target that synced DNS records point at (IP → A/AAAA, else CNAME)."},"effective_metrics_store":{"$ref":"#/components/schemas/MetricsStoreKind","description":"The storage backend the runtime is **actually** using for metrics,\nafter reconciling the `monitoring.store` toggle with the server's\n`TEMPS_CLICKHOUSE_*` configuration. When `monitoring.store` is\n`click_house` but those env vars are not fully set, the runtime falls\nback to TimescaleDB — in that case this reports `timescale_db` even\nthough `monitoring.store` says `click_house`. The UI shows this as the\neffective backend and warns when it diverges from the configured store."},"effective_observability_store":{"$ref":"#/components/schemas/MetricsStoreKind","description":"Storage backend actually used for proxy logs, OTel spans, and OTel\nmetrics. OTel logs remain TimescaleDB-backed. Unlike resource metrics,\nthese domains switch to ClickHouse whenever the server-level ClickHouse\nconnection is configured; they do not use the monitoring store toggle."},"external_url":{"type":["string","null"]},"insecure_tls":{"type":"boolean"},"internal_url":{"type":["string","null"]},"letsencrypt":{"$ref":"#/components/schemas/LetsEncryptSettings"},"monitored_services_count":{"type":["integer","null"],"format":"int64","description":"Number of enabled, running services the MetricsScraper currently\nincludes. Used for the lightweight storage estimate in the UI.","minimum":0},"monitoring":{"$ref":"#/components/schemas/MonitoringSettingsMasked"},"multi_node":{"$ref":"#/components/schemas/MultiNodeSettingsMasked"},"observability_compression":{"$ref":"#/components/schemas/ObservabilityCompressionSettings","description":"TimescaleDB compression delays for immutable proxy logs and OTel spans."},"observability_retention":{"$ref":"#/components/schemas/ObservabilityRetentionSettings","description":"Retention windows for raw proxy logs and OpenTelemetry data."},"preview_domain":{"type":"string"},"preview_gateway":{"$ref":"#/components/schemas/PreviewGatewaySettingsMasked"},"rate_limiting":{"$ref":"#/components/schemas/RateLimitSettings"},"require_mfa_for_admins":{"type":"boolean","description":"When enabled, Admin-role accounts without MFA enrolled are rejected\nat password login (bherila/temps#32). SSO/OIDC logins are unaffected."},"screenshots":{"$ref":"#/components/schemas/ScreenshotSettings"},"security_headers":{"$ref":"#/components/schemas/SecurityHeadersSettings"},"setup_complete":{"type":"boolean","description":"Whether `temps setup` has been run at least once. The web onboarding\nwizard checks this field on load and skips itself when true."}}},"ApplyHostnameModeRequest":{"type":"object","description":"Request to apply a hostname mode (recompute + optional DNS sync).","required":["mode"],"properties":{"mode":{"type":"string","description":"Target mode to apply: `\"standard\"` or `\"flat\"`."},"sync_dns":{"type":"boolean","description":"Also reconcile the provider's DNS zone for the affected hostnames."}}},"ArchiveFlagResponse":{"type":"object","required":["key"],"properties":{"archived_at":{"type":["string","null"]},"key":{"type":"string"}}},"ArchiveMode":{"type":"string","enum":["off","on","always","unknown"]},"AssignRoleRequest":{"type":"object","required":["user_id","role_type"],"properties":{"role_type":{"type":"string"},"user_id":{"type":"integer","format":"int32"}}},"AttachScheduleServicesRequest":{"type":"object","description":"Body for `POST /api/backups/schedules/{id}/services` — attach external\nservices to a backup schedule. Idempotent.","required":["service_ids"],"properties":{"service_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"External service ids to attach. Duplicates are de-duplicated server-side."}}},"AttachScheduleServicesResponse":{"type":"object","description":"Response for `POST /api/backups/schedules/{id}/services`.","required":["inserted","total_attached"],"properties":{"inserted":{"type":"integer","format":"int64","description":"Number of rows actually inserted (excludes rows skipped by\n`ON CONFLICT DO NOTHING`).","minimum":0},"total_attached":{"type":"integer","description":"Total number of services now attached to the schedule.","minimum":0}}},"AuditLogIpInfo":{"type":"object","description":"IP address information in audit log","required":["ip"],"properties":{"city":{"type":["string","null"],"description":"City name","example":"San Francisco"},"country":{"type":["string","null"],"description":"Country code","example":"US"},"ip":{"type":"string","description":"IP address","example":"192.168.1.1"},"latitude":{"type":["number","null"],"format":"double","description":"Latitude","example":37.7749},"longitude":{"type":["number","null"],"format":"double","description":"Longitude","example":122.4194}}},"AuditLogResponse":{"type":"object","description":"Response type for audit log entries","required":["id","operation_type","audit_date"],"properties":{"audit_date":{"type":"integer","format":"int64","description":"When the action occurred","example":11932193},"data":{"description":"Additional context about the action"},"id":{"type":"integer","format":"int32","description":"Unique identifier for the audit log entry"},"ip_address":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AuditLogIpInfo","description":"IP address details"}]},"operation_type":{"type":"string","description":"The type of action that was performed","example":"USER_LOGIN"},"user":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AuditLogUserInfo","description":"User details who performed the action"}]},"user_id":{"type":["integer","null"],"format":"int32","description":"The user who performed the action (`null` when that account has\nsince been deleted; `data` retains the original actor context)"}}},"AuditLogUserInfo":{"type":"object","description":"User information in audit log","required":["id","name","email"],"properties":{"email":{"type":"string","description":"User's email","example":"john.doe@example.com"},"id":{"type":"integer","format":"int32","description":"User ID"},"name":{"type":"string","description":"User's name","example":"John Doe"}}},"AuthFlavorDto":{"type":"object","description":"One auth flavor surfaced to the UI. Mirrors `AuthFlavor` in the catalog\nbut without the seed-path / env-var fields the frontend doesn't need\n(those are server-side only — exposing them just bloats the response).","required":["id","label","description","format"],"properties":{"description":{"type":"string"},"env_var":{"type":["string","null"],"description":"For `api_key` format: the env var name that will be set inside the\nsandbox. Useful for showing the user \"we'll set OPENAI_API_KEY\" so\nthey know what their key controls."},"format":{"type":"string","description":"`api_key`, `oauth_token`, or `config_file` — drives which input UI\nthe settings page renders (single-line vs. multi-line textarea)."},"id":{"type":"string"},"label":{"type":"string"}}},"AuthResponse":{"type":"object","required":["success","message","mfa_required"],"properties":{"message":{"type":"string"},"mfa_required":{"type":"boolean"},"success":{"type":"boolean"},"user_id":{"type":["integer","null"],"format":"int32"}}},"AuthStatusResponse":{"type":"object","required":["status"],"properties":{"cli_token":{"type":["string","null"]},"status":{"type":"string"}}},"AuthTokenResponse":{"type":"object","required":["access_token","refresh_token","expires_at"],"properties":{"access_token":{"type":"string"},"expires_at":{"type":"integer","format":"int64"},"refresh_token":{"type":"string"}}},"AutoWatchParams":{"type":"object","description":"Auto-watch (Watchdog-style) detector parameters (stub — not evaluated).","properties":{"direction":{"$ref":"#/components/schemas/Direction","description":"The engine self-tunes the band; the user supplies only the direction."}}},"AutofixRunConfig":{"type":"object","description":"User-chosen per-run options, persisted as JSON in `agent_runs.run_config`.\nEvery field is optional — unset fields fall back to the provider defaults\nin settings, then to built-in defaults.","properties":{"branch":{"type":["string","null"],"description":"Branch to clone instead of the project's main branch.","default":null},"max_turns":{"type":["integer","null"],"format":"int32","description":"Per-run turn cap applied to every phase of this run. Only enforced\nfor CLIs with a turn flag (Claude Code); Codex/OpenCode run to\ncompletion. `None` uses the provider's per-phase defaults.","default":null},"model":{"type":["string","null"],"description":"Model id for the chosen provider. `None` uses the provider's saved\ndefault model, or the CLI's own default.","default":null},"provider":{"type":["string","null"],"description":"AI provider id (\"claude_cli\", \"codex_cli\", \"opencode\"). `None` uses\nthe platform default provider from agent sandbox settings.","default":null}}},"AutofixerRunResponse":{"type":"object","required":["id","project_id","status","tokens_input","tokens_output","files_changed","created_at"],"properties":{"ai_model":{"type":["string","null"]},"ai_output":{"type":["string","null"]},"ai_provider":{"type":["string","null"],"description":"AI provider slug this run executes with (e.g. claude_cli, codex_cli)."},"analysis":{"type":["string","null"]},"branch_name":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"files_changed":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"phase":{"type":["string","null"]},"pr_number":{"type":["integer","null"],"format":"int32"},"pr_url":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"run_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AutofixRunConfig","description":"Per-run options the run was started with; used to prefill the\nretry / start-over dialog."}]},"started_at":{"type":["string","null"]},"status":{"type":"string"},"tokens_input":{"type":"integer","format":"int32"},"tokens_output":{"type":"integer","format":"int32"},"trigger_source_id":{"type":["integer","null"],"format":"int32"},"user_context":{"type":["string","null"]}}},"AutofixerRunWithLogsResponse":{"type":"object","required":["run","logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunLogResponse"}},"run":{"$ref":"#/components/schemas/AutofixerRunResponse"}}},"AvailableContainerInfo":{"type":"object","description":"Available Docker container that can be imported as a service","required":["container_id","container_name","image","version","service_type","is_running"],"properties":{"container_id":{"type":"string","description":"Container ID or name","example":"abc123def456"},"container_name":{"type":"string","description":"Container display name","example":"my-postgres"},"exposed_ports":{"type":"array","items":{"type":"integer","format":"int32","minimum":0},"description":"Exposed ports (e.g., [5432] for PostgreSQL, [6379] for Redis)"},"image":{"type":"string","description":"Docker image name (e.g., \"gotempsh/postgres-walg:18-bookworm\")","example":"gotempsh/postgres-walg:18-bookworm"},"is_running":{"type":"boolean","description":"Whether the container is currently running","example":true},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute","description":"Service type this container represents"},"version":{"type":"string","description":"Extracted version from image","example":"18"}}},"AvailablePermissions":{"type":"object","description":"Response containing all available permissions for frontend validation","required":["permissions","roles"],"properties":{"permissions":{"type":"array","items":{"$ref":"#/components/schemas/PermissionInfo"},"description":"All available permissions in the system"},"roles":{"type":"array","items":{"$ref":"#/components/schemas/RoleInfo"},"description":"All available roles"}}},"BackupAlertListResponse":{"type":"object","description":"Response body for the list-backup-alerts endpoint.","required":["alerts"],"properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/BackupAlertResponse"},"description":"All currently open (unresolved) alerts, newest first."}}},"BackupAlertResponse":{"type":"object","description":"A single open backup alert surfaced in the UI banner.\n\nAlerts are auto-opened by the watcher and auto-resolved when the triggering\ncondition clears. No manual dismiss is required or supported.\n\nThe optional `schedule_s3_source_id` field is included so the UI can\ndeep-link an `overdue_schedule` alert to the S3 source detail page that\nhosts the schedule. `stalled_job` alerts no longer carry a deep-link\ntarget — the alert message text contains the backup id for display.","required":["id","kind","severity","message","opened_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Database id of the alert row."},"kind":{"type":"string","description":"`\"overdue_schedule\"` or `\"stalled_job\"`."},"message":{"type":"string","description":"Human-readable description of the alert condition."},"opened_at":{"type":"string","description":"RFC 3339 timestamp when the alert was opened.","example":"2026-05-15T10:00:00Z"},"schedule_id":{"type":["integer","null"],"format":"int32","description":"FK to `backup_schedules.id`. Set for `overdue_schedule` alerts."},"schedule_name":{"type":["string","null"],"description":"Human-readable name of the linked schedule, if applicable."},"schedule_s3_source_id":{"type":["integer","null"],"format":"int32","description":"FK to `backup_schedules.s3_source_id`. The UI uses this to deep-link\nthe alert to the S3 source detail page that hosts the schedule.\nSet for `overdue_schedule` alerts."},"severity":{"type":"string","description":"`\"warning\"` or `\"critical\"`."}}},"BackupResponse":{"type":"object","description":"Response type for backup","required":["id","name","backup_id","backup_type","state","started_at","s3_source_id","s3_location","metadata","compression_type","created_by","tags"],"properties":{"attempts":{"type":["integer","null"],"format":"int32","description":"How many times this job has been claimed and run. `null` for legacy\nbackups with no `backup_jobs` row."},"backup_id":{"type":"string"},"backup_type":{"type":"string"},"checksum":{"type":["string","null"]},"completed_at":{"type":["integer","null"],"format":"int64"},"compression_type":{"type":"string"},"created_by":{"type":"integer","format":"int32"},"current_step":{"type":["string","null"],"description":"Name of the engine step currently executing (e.g., `\"walg_push\"`).\n`null` when no `backup_jobs` row exists for this backup (legacy rows\npre-dating ADR-014), or when the job has not yet completed its first step."},"error_message":{"type":["string","null"]},"expires_at":{"type":["integer","null"],"format":"int64"},"external_service":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ExternalServiceSummary","description":"External service that owns this backup (Redis, Postgres, etc.).\n`null` for control-plane backups (the Temps server's own database)."}]},"file_count":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"live_size_bytes":{"type":["integer","null"],"format":"int64","description":"Best-effort partial size while a backup is still running, computed\nby listing the S3 prefix. Null when the backup is finished\n(`size_bytes` is authoritative in that case)."},"max_attempts":{"type":["integer","null"],"format":"int32","description":"Maximum attempts before the job is permanently failed. `null` for\nlegacy backups."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Resolved wall-clock timeout for this backup job (seconds). `null` for\nlegacy backups. Derived from the three-tier resolution order:\ncaller override → schedule override → engine default."},"metadata":{},"name":{"type":"string"},"s3_location":{"type":"string"},"s3_source_id":{"type":"integer","format":"int32"},"schedule_id":{"type":["integer","null"],"format":"int32"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Final size of the backup once completed. Null while running."},"started_at":{"type":"integer","format":"int64"},"state":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}}},"BackupScheduleResponse":{"type":"object","description":"Response type for backup schedule","required":["id","name","backup_type","retention_period","s3_source_id","schedule_expression","enabled","created_at","updated_at","tags","target_all_services","include_control_plane"],"properties":{"backup_type":{"type":"string"},"created_at":{"type":"integer","format":"int64"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"include_control_plane":{"type":"boolean","description":"When `true`, every run also produces a `control_plane` backup\n(Temps's own Postgres). When `false`, only the external service\nfan-out happens."},"last_run":{"type":["integer","null"],"format":"int64"},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Per-schedule wall-clock timeout override for backup jobs (seconds).\n`null` means the engine-family default is used. See\n`temps_backup_core::timeouts::default_max_runtime_secs`."},"name":{"type":"string"},"next_run":{"type":["integer","null"],"format":"int64"},"retention_period":{"type":"integer","format":"int32"},"s3_source_id":{"type":"integer","format":"int32"},"schedule_expression":{"type":"string","example":"0 0 * * *"},"tags":{"type":"array","items":{"type":"string"}},"target_all_services":{"type":"boolean","description":"When `true`, the schedule auto-includes every external service on\nthe host (and any future ones). When `false`, the schedule only\ntargets services attached via `backup_schedule_services`."},"updated_at":{"type":"integer","format":"int64"}}},"BitbucketAuthInput":{"oneOf":[{"type":"object","description":"Personal / Workspace / Repository Access Token.","required":["token","type"],"properties":{"token":{"type":"string","description":"The Bitbucket access token value."},"type":{"type":"string","enum":["access_token"]}}},{"type":"object","description":"HTTP Basic / App Password authentication.","required":["username","password","type"],"properties":{"password":{"type":"string","description":"App password generated in Bitbucket security settings."},"type":{"type":"string","enum":["app_password"]},"username":{"type":"string","description":"Bitbucket account username."}}}],"description":"Authentication input for a Bitbucket Cloud provider. Use `access_token` for\na Repository or Workspace Access Token (PAT), or `username` + `app_password`\nfor App Password (HTTP Basic) authentication."},"BlobResponse":{"type":"object","description":"Response after uploading a blob","required":["url","pathname","contentType","size","uploadedAt"],"properties":{"contentType":{"type":"string","description":"Content type of the blob","example":"image/png"},"pathname":{"type":"string","description":"Original pathname","example":"images/avatar-abc123.png"},"size":{"type":"integer","format":"int64","description":"Size in bytes","example":12345},"uploadedAt":{"type":"string","format":"date-time","description":"Upload timestamp","example":"2025-01-03T12:00:00Z"},"url":{"type":"string","description":"URL path to access the blob","example":"/api/blob/123/images/avatar-abc123.png"}}},"BlobStatusResponse":{"type":"object","description":"Response for Blob service status","required":["enabled","healthy"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image being used","example":"ghcr.io/rustfs/rustfs:0.5.0"},"enabled":{"type":"boolean","description":"Whether the Blob service is enabled","example":true},"healthy":{"type":"boolean","description":"Whether the service is healthy","example":true},"version":{"type":["string","null"],"description":"Current version (if running)","example":"0.5.0"}}},"BranchInfo":{"type":"object","required":["name","commit_sha","protected"],"properties":{"commit_sha":{"type":"string"},"name":{"type":"string"},"protected":{"type":"boolean"}}},"BranchListResponse":{"type":"object","required":["branches"],"properties":{"branches":{"type":"array","items":{"$ref":"#/components/schemas/BranchInfo"}}}},"BrowserCount":{"type":"object","required":["browser","count","percentage"],"properties":{"browser":{"type":"string"},"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"}}},"BrowsersQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"BuildConfiguration":{"type":"object","description":"Build configuration (for building images from source)","required":["context","args"],"properties":{"args":{"type":"object","description":"Build arguments","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"context":{"type":"string","description":"Build context (Dockerfile path or buildpack)"},"dockerfile":{"type":["string","null"],"description":"Dockerfile path (relative to context)"},"target":{"type":["string","null"],"description":"Target stage (for multi-stage builds)"}}},"BuildLimitsSettings":{"type":"object","description":"Control-plane build resource limits.\n\nCaps how many builds run concurrently AND how much CPU/memory each build\nis allowed to consume. A single global semaphore in the deployer crate\ngates every `DockerRuntime::build_image` call to `max_concurrent`. When\nthe semaphore is full, additional builds queue and wait — they do not\nfail. Per-build CPU/memory caps are forwarded to Docker via\n`BuildImageOptions { memory, cpuquota, cpuperiod }`.\n\n`cpu_limit_cores = 0.0` or `memory_limit_mb = 0` means \"no explicit cap\"\n— fall back to the legacy 50%-of-host heuristic for backwards\ncompatibility with operators who never visit the settings page.","properties":{"cpu_limit_cores":{"type":"number","format":"float","description":"CPU cores allowed per build (float, e.g. 2.0 = 2 cores, 0.5 = half\na core). 0 means \"use the legacy 50%-of-host default\".","default":0.0,"example":2.0,"minimum":0},"max_concurrent":{"type":"integer","format":"int32","description":"Maximum number of `docker build` operations allowed to run at the\nsame time on the control plane. Additional builds queue. Min 1.","default":2,"example":2,"minimum":1},"memory_limit_mb":{"type":"integer","format":"int32","description":"Memory allowed per build, in megabytes. 0 means \"use the legacy\n50%-of-host default\". Docker enforces this as a hard cap — builds\nthat exceed it OOM-kill.","default":0,"example":2048,"minimum":0}}},"CancelBackupResponse":{"type":"object","description":"Response body for cancel endpoints.","required":["cancelled"],"properties":{"cancelled":{"type":"integer","format":"int64","description":"Number of rows that were actually flipped to `failed`. `0` is a valid\nsuccess and means the backup was already terminal — the call is\nidempotent.","minimum":0}}},"CertStatusResponse":{"type":"object","description":"Current on-demand cert status for a single hostname (ADR-018 §5). Backs\n`GET /domains/by-host/{hostname}/cert-status`.","required":["hostname"],"properties":{"backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand negative-cache deadline (epoch millis), when in backoff."},"hostname":{"type":"string","description":"SNI hostname."},"last_attempt":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/OnDemandCertAttemptResponse","description":"The most recent on-demand issuance attempt for this hostname, if any."}]},"status":{"type":["string","null"],"description":"Current cert lifecycle status from the `domains` row, when one exists."}}},"ChallengeConfig":{"type":"object","description":"Challenge configuration (future feature)\nFor CAPTCHA, JS challenges, proof-of-work, etc.","required":["challengeType","difficulty"],"properties":{"challengeType":{"type":"string","description":"Challenge type: \"captcha\", \"js_challenge\", \"proof_of_work\""},"difficulty":{"type":"integer","format":"int32","description":"Challenge difficulty level (1-10)","minimum":0},"protectedPaths":{"type":"array","items":{"type":"string"},"description":"Paths that require challenges"}}},"ChallengeError":{"type":"object","required":["type","detail","status"],"properties":{"detail":{"type":"string","description":"Human-readable error description"},"status":{"type":"integer","format":"int32","description":"HTTP status code"},"type":{"type":"string","description":"Error type (e.g., \"urn:ietf:params:acme:error:unauthorized\")"}}},"ChallengeValidationStatus":{"type":"object","required":["type","url","status","token"],"properties":{"error":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeError","description":"Error details if validation failed"}]},"status":{"type":"string","description":"Challenge status (e.g., \"pending\", \"valid\", \"invalid\")"},"token":{"type":"string","description":"Challenge token"},"type":{"type":"string","description":"Challenge type (e.g., \"dns-01\", \"http-01\")"},"url":{"type":"string","description":"Challenge validation URL"},"validated":{"type":["string","null"],"description":"When the challenge was validated (if successful)"}}},"ChangePasswordRequest":{"type":"object","required":["current_password","new_password"],"properties":{"current_password":{"type":"string","example":"current_password_value"},"mfa_code":{"type":["string","null"],"description":"TOTP code (or recovery code). Required iff the user has MFA enabled.","example":"123456"},"new_password":{"type":"string","example":"new_password_value"},"revoke_other_sessions":{"type":"boolean","description":"When true, every session OTHER than the one making this request is\nrevoked. Defaults to false; the UI surfaces this as a checkbox."}}},"ChangeProjectSourceRequest":{"type":"object","description":"Change a project's source type to a Git-less type (docker_image /\nstatic_files / manual). Switching TO `git` is done via the Git settings\nendpoint (which also supplies the repository + provider connection).","required":["source_type"],"properties":{"source_type":{"$ref":"#/components/schemas/SourceType"}}},"ChatCompletionChoice":{"type":"object","required":["index","message"],"properties":{"finish_reason":{"type":["string","null"]},"index":{"type":"integer","format":"int32"},"message":{"$ref":"#/components/schemas/ChatMessage"}}},"ChatCompletionRequest":{"allOf":[{"type":["object","null"],"description":"Tolerates extra SDK fields (stream_options, logprobs, etc.)","additionalProperties":{},"propertyNames":{"type":"string"}},{"type":"object","required":["model","messages"],"properties":{"frequency_penalty":{"type":["number","null"],"format":"double"},"max_tokens":{"type":["integer","null"],"format":"int64"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/ChatMessage"}},"model":{"type":"string"},"n":{"type":["integer","null"],"format":"int32"},"presence_penalty":{"type":["number","null"],"format":"double"},"response_format":{},"seed":{"type":["integer","null"],"format":"int64"},"stop":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/StopSequence"}]},"stream":{"type":"boolean"},"temperature":{"type":["number","null"],"format":"double"},"tool_choice":{},"tools":{"type":["array","null"],"items":{}},"top_p":{"type":["number","null"],"format":"double"},"user":{"type":["string","null"]}}}],"description":"OpenAI-compatible chat completion request.\nUses `deny_unknown_fields = false` (serde default) so that SDK-specific\nfields like `stream_options`, `logprobs`, `top_logprobs`, `logit_bias`,\n`parallel_tool_calls`, etc. are silently accepted without breaking."},"ChatCompletionResponse":{"type":"object","required":["id","object","created","model","choices"],"properties":{"choices":{"type":"array","items":{"$ref":"#/components/schemas/ChatCompletionChoice"}},"created":{"type":"integer","format":"int64"},"id":{"type":"string"},"model":{"type":"string"},"object":{"type":"string"},"usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UsageInfo"}]}}},"ChatMessage":{"type":"object","required":["role"],"properties":{"content":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/MessageContent"}]},"name":{"type":["string","null"]},"role":{"type":"string"},"tool_call_id":{"type":["string","null"]},"tool_calls":{"type":["array","null"],"items":{}}}},"ChildBackupEntryResponse":{"type":"object","description":"A single child backup entry in the `GET /backups/{id}/children` response.\n\nEach entry corresponds to one `external_service_backups` row joined with\n`external_services`, providing service metadata without a second request.","required":["id","service_id","service_name","service_type","state","backup_type","started_at","s3_location","compression_type"],"properties":{"backup_type":{"type":"string","description":"Backup variant (e.g. \"full\", \"incremental\")."},"compression_type":{"type":"string","description":"Compression algorithm used (e.g. \"gzip\", \"lz4\")."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When the child backup finished, if known.","example":"2025-01-15T14:35:00.456Z"},"id":{"type":"integer","format":"int32","description":"Row ID from `external_service_backups`."},"s3_location":{"type":"string","description":"Object key or `s3://` URL where the backup data lives."},"service_id":{"type":"integer","format":"int32","description":"FK to `external_services.id`."},"service_name":{"type":"string","description":"Human-readable name of the external service (e.g. \"redis-prod\")."},"service_type":{"type":"string","description":"Service type string (e.g. \"postgres\", \"redis\", \"mongodb\", \"s3\").","example":"postgres"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the child backup in bytes, if available."},"started_at":{"type":"string","description":"When the child backup started (RFC 3339).","example":"2025-01-15T14:30:00.123Z"},"state":{"type":"string","description":"Current state: \"pending\" | \"running\" | \"completed\" | \"failed\"."}}},"ChildBackupListResponse":{"type":"object","description":"Response body for `GET /backups/{id}/children`.\n\nReturns an empty `children` list (not 404) when the parent backup has no\nchild records (e.g. control-plane backups).","required":["children"],"properties":{"children":{"type":"array","items":{"$ref":"#/components/schemas/ChildBackupEntryResponse"},"description":"Zero or more child backup entries ordered by `external_service_backups.id` ASC."}}},"CleanupExpiredBackupsRequest":{"type":"object","properties":{"expected_backup_ids":{"type":["array","null"],"items":{"type":"string"},"description":"Exact candidates returned by the dry run. Execution fails if the\nretention selection has changed since preview."}}},"CliDeviceApproveRequest":{"type":"object","required":["user_code"],"properties":{"user_code":{"type":"string"}}},"CliDeviceApproveResponse":{"type":"object","required":["user_code","status"],"properties":{"status":{"type":"string"},"user_code":{"type":"string"}}},"CliDeviceLookupResponse":{"type":"object","required":["user_code","status","expires_at"],"properties":{"client_name":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time"},"requested_ip":{"type":["string","null"]},"status":{"type":"string","description":"`pending` | `approved` | `denied` | `expired`."},"user_code":{"type":"string"}}},"CliDevicePollRequest":{"type":"object","required":["device_code"],"properties":{"device_code":{"type":"string"}}},"CliDevicePollResponse":{"oneOf":[{"type":"object","description":"Still waiting on the user to approve in the browser.","required":["status"],"properties":{"status":{"type":"string","enum":["authorization_pending"]}}},{"type":"object","description":"CLI is polling faster than the server-suggested interval.","required":["status"],"properties":{"status":{"type":"string","enum":["slow_down"]}}},{"type":"object","description":"User denied the request in the browser.","required":["status"],"properties":{"status":{"type":"string","enum":["access_denied"]}}},{"type":"object","description":"The session has expired without approval.","required":["status"],"properties":{"status":{"type":"string","enum":["expired_token"]}}},{"type":"object","description":"The session was approved; this is the only response that carries\nthe API key. The key is returned exactly once and then cleared\nfrom the session row.","required":["user_id","email","role","api_key","key_prefix","status"],"properties":{"api_key":{"type":"string"},"email":{"type":"string"},"expires_at":{"type":["string","null"],"format":"date-time"},"key_prefix":{"type":"string"},"role":{"type":"string"},"status":{"type":"string","enum":["approved"]},"user_id":{"type":"integer","format":"int32"}}}]},"CliDeviceStartRequest":{"type":"object","properties":{"client_name":{"type":["string","null"],"description":"Friendly hostname / client identifier shown in the browser approval\nscreen. Sanitized before display.","example":"dviejo-mac.local"}}},"CliDeviceStartResponse":{"type":"object","required":["device_code","user_code","verification_uri","verification_uri_complete","expires_in","interval"],"properties":{"device_code":{"type":"string","description":"Opaque secret the CLI polls with. Never display to a human."},"expires_in":{"type":"integer","format":"int64","description":"Seconds until the device_code expires."},"interval":{"type":"integer","format":"int64","description":"Suggested polling interval, in seconds."},"user_code":{"type":"string","description":"Short human-readable code the user types into the browser.","example":"ABCD-1234"},"verification_uri":{"type":"string","description":"Base verification URL — the CLI may display this when the\npre-filled URL is too long to be useful.","example":"https://temps.example.com/cli-login"},"verification_uri_complete":{"type":"string","description":"`verification_uri` with `user_code` pre-filled. Open this directly.","example":"https://temps.example.com/cli-login/ABCD-1234"}}},"CliLoginRequest":{"type":"object","required":["username","password"],"properties":{"password":{"type":"string"},"username":{"type":"string"}}},"CloudProvider":{"type":"string","description":"Cloud provider detected from node metadata","enum":["aws","gcp","azure","hetzner","digitalocean","other"]},"CloudflareConfig":{"type":"object","description":"Configuration for a Cloudflare Email Sending notification provider.\n\nNotifications are delivered through Cloudflare's transactional Email Sending\nAPI. Only the account, token, sender and recipients are configured here —\nsubject and body are derived from each notification.","required":["account_id","api_token","from_address","to_addresses"],"properties":{"account_id":{"type":"string","description":"Cloudflare account id that owns the Email Sending configuration.","example":"023e105f4ecef8ad9ca31a8372d0c353"},"api_token":{"type":"string","description":"Cloudflare API token with the Email Sending permission. Encrypted at\nrest and masked in normal API responses."},"from_address":{"type":"string","description":"Verified sender address (must belong to a domain enabled for Cloudflare\nEmail Sending).","example":"welcome@infracf.example.com"},"from_name":{"type":["string","null"],"description":"Optional human-friendly sender name shown in the recipient's inbox."},"to_addresses":{"type":"array","items":{"type":"string"},"description":"Recipients that should receive the notification."}}},"ClusterCapacity":{"type":"object","description":"Total cluster capacity (sum of node allocatable resources)","required":["node_count","cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"Total allocatable CPU in millicores"},"memory_mb":{"type":"integer","format":"int64","description":"Total allocatable memory in MB"},"node_count":{"type":"integer","description":"Number of nodes","minimum":0}}},"ClusterDnsSettings":{"type":"object","description":"Cluster-DNS resolver settings (ADR-024, experimental beta).\n\nWhen `enabled`, the Temps control plane starts a Hickory DNS resolver and\ninjects it as the first nameserver into every deployed container via\n`HostConfig.Dns` — giving containers the ability to resolve `*.temps.local`\nFQDNs for service-to-service communication. Worker nodes pick this flag up\nfrom the `/api/internal/nodes/{id}/network/peers` wire response and gate\ntheir own per-node resolver the same way.\n\n**Default: `false` (disabled).**\n\nWhy disabled by default: a production incident showed that when the injected\nHickory resolver was slow or transiently unresponsive for a non-`*.temps.local`\n(external) hostname, glibc's resolver cycled through all three nameservers\n(`172.20.0.1`, `1.1.1.1`, `8.8.8.8`) at ~5 s timeout × 2 attempts each,\ncausing 22–27 s delays for outbound TCP connections. Disabling the injection\nrestores Docker's embedded DNS as the sole resolver, eliminating that failure\nmode. Operators running single/multi-node installs that depend on\n`*.temps.local` resolution must explicitly opt in by setting `enabled: true`.\n\n`bool` defaults to `false` in Rust and JSON (`#[serde(default)]`), so the\nsafe-off behaviour is automatic for new installs and legacy settings rows.","properties":{"enabled":{"type":"boolean","description":"Master switch. When `false` (default), no custom DNS is injected into\ncontainers — they use Docker's embedded DNS which forwards to the host's\nown `resolv.conf`. When `true`, the control-plane Hickory resolver is\nstarted and its bridge IP is injected as the first nameserver so\n`*.temps.local` FQDNs resolve inside containers.","default":false,"example":false}}},"ClusterHealthReportResponse":{"type":"object","description":"Response body for `GET /external-services/{id}/cluster-health`.","required":["checked_at","monitor_response_ms","members"],"properties":{"checked_at":{"type":"string","description":"ISO-8601 wall-clock when the report was generated.","example":"2025-10-12T12:15:47.609192Z"},"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberHealthResponse"}},"monitor_error":{"type":["string","null"],"description":"Set when the monitor itself was unreachable. UI shows a banner."},"monitor_response_ms":{"type":"integer","format":"int64","description":"Round-trip to query the monitor (ms)."}}},"ClusterMemberHealthResponse":{"type":"object","description":"One row in the cluster Members table — see `GET /external-services/{id}/cluster-health`.","required":["nodename","nodehost","nodeport","reported_state","goal_state","health","seconds_since_report","candidate_priority","replication_quorum"],"properties":{"candidate_priority":{"type":"integer","format":"int32"},"goal_state":{"type":"string","description":"What the monitor *wants* the node to be. Differs from\n`reported_state` mid-transition (failover, demotion, etc.)."},"health":{"type":"integer","format":"int32","description":"pg_auto_failover liveness signal: `1` healthy, `0` unknown\n(no recent report), `-1` unhealthy."},"nodehost":{"type":"string"},"nodename":{"type":"string"},"nodeport":{"type":"integer","format":"int32"},"replay_lag_ms":{"type":["integer","null"],"format":"int64","description":"`replay_lag` from `pg_stat_replication`, in milliseconds."},"replication_quorum":{"type":"boolean"},"reported_state":{"type":"string","description":"What the node *last told the monitor* it was. Stale during outages."},"seconds_since_report":{"type":"integer","format":"int64","description":"Wall-clock seconds since the node last reported in."},"sync_state":{"type":["string","null"],"description":"`sync` / `quorum` / `async` for secondaries; `null` for the primary."}}},"ClusterMemberRequest":{"type":"object","description":"Request spec for a single cluster member.","required":["role"],"properties":{"node_id":{"type":["integer","null"],"format":"int32","description":"Target worker node ID. Omit or null to run on the control plane."},"role":{"type":"string","description":"Service-type-specific role (e.g., \"monitor\", \"primary\", \"replica\")","example":"primary"}}},"CmdBody":{"type":"object","required":["command"],"properties":{"args":{"type":"array","items":{"type":"string"},"description":"Arguments to pass to the binary. Defaults to empty."},"command":{"type":"string","description":"Binary name (argv[0]) — e.g. `\"ls\"`, `\"node\"`. The SDK sends this\nseparately from `args`."},"cwd":{"type":["string","null"],"description":"Working directory override."},"env":{"type":"object","description":"Extra env vars.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"sudo":{"type":"boolean","description":"When true, the SDK runs the command privileged. We ignore it today\n— the underlying provider always runs as the sandbox's own user."},"wait":{"type":"boolean","description":"When true, the response is an `application/x-ndjson` stream where\nthe first line is the running-command envelope and the second line\nis the finished-command envelope with `exitCode`."}}},"CmdInner":{"type":"object","description":"Inner `command` object — matches the SDK's zod validator exactly.\n`exitCode` is `null` until the command terminates; `startedAt` is Unix\nepoch milliseconds.","required":["id","name","args","cwd","sandboxId","startedAt"],"properties":{"args":{"type":"array","items":{"type":"string"}},"cwd":{"type":"string"},"exitCode":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"name":{"type":"string"},"sandboxId":{"type":"string"},"startedAt":{"type":"integer","format":"int64"}}},"CmdKillBody":{"type":"object","description":"SDK-shaped kill body. The SDK sends `{signal: AbortSignal}` but only\nuses the signal for HTTP request abortion client-side; there's no\nsignal name on the wire.","properties":{"force":{"type":"boolean","description":"Optional: when true, SIGKILL instead of SIGTERM."}}},"CmdResponse":{"type":"object","description":"`@vercel/sandbox` envelope: `{ command: {...} }`.","required":["command"],"properties":{"command":{"$ref":"#/components/schemas/CmdInner"}}},"CommitExistsResponse":{"type":"object","required":["exists"],"properties":{"commit":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CommitInfo","description":"Commit metadata when the requested SHA exists."}]},"commit_sha":{"type":["string","null"]},"exists":{"type":"boolean"}}},"CommitInfo":{"type":"object","required":["sha","message","author","author_email","date"],"properties":{"author":{"type":"string","description":"Author name"},"author_email":{"type":"string","description":"Author email"},"date":{"type":"string","format":"date-time","description":"Commit date in ISO 8601 format","example":"2025-10-12T12:15:47.609192Z"},"message":{"type":"string","description":"Commit message"},"sha":{"type":"string","description":"Commit SHA hash"}}},"CommitListResponse":{"type":"object","required":["commits"],"properties":{"commits":{"type":"array","items":{"$ref":"#/components/schemas/CommitInfo"}}}},"Comparator":{"type":"string","description":"Comparator for static/forecast threshold detectors. Serializes to the\nkeyword forms `gt|gte|lt|lte` (NOT the SQL operators used by\n`temps-monitoring::compare`).","enum":["gt","gte","lt","lte"]},"ComposePublicPort":{"type":"object","description":"A port that should be exposed publicly through the proxy for a compose service.","required":["service","port"],"properties":{"port":{"type":"integer","format":"int32","description":"Container port to expose (e.g. 8123)","minimum":0},"service":{"type":"string","description":"Compose service name (e.g. \"web\", \"clickhouse\")"}}},"ConnectionListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"sort":{"type":["string","null"]}}},"ConnectionListResponse":{"type":"object","required":["connections","total_count","page","per_page"],"properties":{"connections":{"type":"array","items":{"$ref":"#/components/schemas/ConnectionResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"total_count":{"type":"integer","minimum":0}}},"ConnectionResponse":{"type":"object","required":["id","provider_id","account_name","account_type","is_active","is_expired","syncing","synced_repository_count","health_status","consecutive_health_failures","created_at","updated_at"],"properties":{"account_name":{"type":"string"},"account_type":{"type":"string"},"consecutive_health_failures":{"type":"integer","format":"int32"},"created_at":{"type":"string","format":"date-time"},"health_message":{"type":["string","null"],"description":"Human-readable reason when health_status is \"unhealthy\"; null otherwise."},"health_status":{"type":"string","description":"Current health status: \"healthy\", \"unhealthy\", or \"unknown\"."},"id":{"type":"integer","format":"int32"},"installation_id":{"type":["string","null"]},"is_active":{"type":"boolean"},"is_expired":{"type":"boolean"},"last_health_check_at":{"type":["string","null"],"format":"date-time"},"last_synced_at":{"type":["string","null"],"format":"date-time"},"provider_id":{"type":"integer","format":"int32"},"synced_repository_count":{"type":"integer","format":"int32","description":"Running count of repositories persisted by the current (or most\nrecent) sync. Resets to 0 when a new sync begins; useful for showing\nlive progress on large syncs."},"syncing":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"},"user_id":{"type":["integer","null"],"format":"int32"}}},"ConnectionTestResult":{"type":"object","description":"Connection test result","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"ConsoleEventPayload":{"type":"object","description":"Payload for server-side event ingestion via the console API.\n\nThe app backend reads the encrypted `_temps_visitor_id` and `_temps_sid`\ncookie values from the user's request and forwards them here.\nTemps decrypts them server-side to resolve visitor/session identity.","required":["event_name","environment_id","deployment_id"],"properties":{"deployment_id":{"type":"integer","format":"int32","description":"Deployment ID to attribute the event to"},"environment_id":{"type":"integer","format":"int32","description":"Environment ID to attribute the event to"},"event_data":{"description":"Arbitrary JSON event data"},"event_name":{"type":"string","description":"Event name (e.g. \"purchase\", \"signup\", custom event names)"},"request_path":{"type":"string","description":"Page path context (defaults to \"/\")"},"request_query":{"type":"string","description":"Query string context"},"session_id":{"type":["string","null"],"description":"Encrypted `_temps_sid` cookie value from the user's browser"},"visitor_id":{"type":["string","null"],"description":"Encrypted `_temps_visitor_id` cookie value from the user's browser"}}},"ContainerActionResponse":{"type":"object","description":"Response indicating success of container state change","required":["container_id","container_name","action","status","message"],"properties":{"action":{"type":"string"},"container_id":{"type":"string"},"container_name":{"type":"string"},"message":{"type":"string"},"status":{"type":"string"}}},"ContainerDetailResponse":{"type":"object","description":"Detailed container information with environment variables and metrics","required":["id","container_id","container_name","image_name","status","deployment_id","created_at","deployed_at","container_port","environment_variables"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"container_port":{"type":"integer","format":"int32","description":"Port inside the container"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None when no limit is configured."},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"deployed_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"deployment_id":{"type":"integer","format":"int32"},"environment_variables":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarResponse"},"description":"Environment variables (sensitive values masked)"},"error_message":{"type":["string","null"],"description":"Free-form error string from Docker's container state on exit."},"exit_code":{"type":["integer","null"],"format":"int32","description":"Process exit code reported by Docker. None while still running."},"exit_reason":{"type":["string","null"],"description":"Human-readable reason the container exited."},"finished_at":{"type":["string","null"],"description":"When the container exited (Docker's FinishedAt). None while running.","example":"2025-10-12T12:16:47.609192Z"},"host_port":{"type":["integer","null"],"format":"int32","description":"Port on the host machine"},"id":{"type":"integer","format":"int32"},"image_name":{"type":"string"},"oom_killed":{"type":["boolean","null"],"description":"True when Docker's OOM killer terminated the container."},"ready_at":{"type":["string","null"],"example":"2025-10-12T12:16:47.609192Z"},"resource_limits":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourceLimitsResponse","description":"Resource limits"}]},"restart_count":{"type":["integer","null"],"format":"int64","description":"Container restart count from Docker"},"service_name":{"type":["string","null"],"description":"Compose service name (e.g. \"web\", \"redis\"). None for single-container deployments."},"service_url":{"type":["string","null"],"description":"Per-service URL for compose deployments"},"started_at":{"type":["string","null"],"description":"When the container's main process most recently started.","example":"2025-10-12T12:15:50.000000Z"},"status":{"type":"string"}}},"ContainerEnvironmentVariableValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"ContainerInfoResponse":{"type":"object","required":["container_id","container_name","image_name","status","created_at"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None when no limit is configured."},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"error_message":{"type":["string","null"],"description":"Free-form error string from Docker's container state on exit."},"exit_code":{"type":["integer","null"],"format":"int32","description":"Process exit code reported by Docker. None while still running."},"exit_reason":{"type":["string","null"],"description":"Human-readable reason the container exited (e.g. \"OOMKilled\",\n\"Killed by SIGKILL (exit code 137)\", \"Exit code 1\"). None while running."},"finished_at":{"type":["string","null"],"description":"When the container exited (Docker's FinishedAt). None while running.","example":"2025-10-12T12:16:47.609192Z"},"image_name":{"type":"string"},"node_name":{"type":["string","null"],"description":"Node name where this container is running. None for local (single-node) deployments."},"oom_killed":{"type":["boolean","null"],"description":"True when Docker's OOM killer terminated the container."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Container restart count from Docker. The UI shows a chip when this is\n> 0 so a crash loop is visible without opening detail."},"service_name":{"type":["string","null"],"description":"Compose service name (e.g. \"web\", \"redis\"). None for single-container deployments."},"service_url":{"type":["string","null"],"description":"Per-service URL for compose deployments (e.g. \"https://web-myapp.localho.st\")"},"started_at":{"type":["string","null"],"description":"When the container's main process most recently started. The UI uses\nthis for the uptime label so the count resets when a container is\nrestarted in place. None for containers that never started.","example":"2025-10-12T12:15:50.000000Z"},"status":{"type":"string"}}},"ContainerInventoryItem":{"type":"object","description":"A container reported by the agent during heartbeat reconciliation.","required":["container_id","container_name"],"properties":{"container_id":{"type":"string","description":"Docker container ID"},"container_name":{"type":"string","description":"Docker container name"}}},"ContainerListResponse":{"type":"object","required":["containers","total"],"properties":{"containers":{"type":"array","items":{"$ref":"#/components/schemas/ContainerInfoResponse"}},"total":{"type":"integer","minimum":0}}},"ContainerLogSettings":{"type":"object","description":"Docker container log rotation settings\nControls the `--log-opt max-size` and `--log-opt max-file` for containers","properties":{"max_file":{"type":"integer","format":"int32","description":"Maximum number of rotated log files to keep (e.g., 3 means up to 3 x max_size total)","default":3,"example":3,"minimum":0},"max_size":{"type":"string","description":"Maximum size of each log file (e.g., \"50m\", \"100m\", \"1g\")\nDocker default is unlimited; we default to \"50m\" to prevent disk exhaustion","default":"50m","example":"50m"},"service_max_file":{"type":"integer","format":"int32","description":"Maximum rotated log files for external service containers","default":3,"example":3,"minimum":0},"service_max_size":{"type":"string","description":"Maximum size for external service container logs (postgres, redis, etc.)\nDefaults to \"20m\" since services are typically less verbose than app containers","default":"20m","example":"20m"}}},"ContainerLogsQuery":{"type":"object","properties":{"container_name":{"type":["string","null"],"description":"Optional container name to get logs from (if deployment has multiple containers)"},"end_date":{"type":["integer","null"],"format":"int64"},"follow":{"type":"boolean","description":"Follow log output in real-time (default: true for backward compatibility)"},"start_date":{"type":["integer","null"],"format":"int64"},"tail":{"type":["string","null"]},"timestamps":{"type":"boolean","description":"Include timestamps in log output (default: false)"}}},"ContainerMetricHistoryPoint":{"type":"object","description":"One bucketed data point of a container resource metric time series.","required":["time","value"],"properties":{"time":{"type":"string","description":"Bucket timestamp (ISO 8601 with `Z` suffix).","example":"2025-10-12T12:15:00+00:00"},"value":{"type":"number","format":"double","description":"Averaged metric value for the bucket."}}},"ContainerMetricsHistoryQuery":{"type":"object","description":"Query parameters for the container metrics history endpoint.","required":["metric"],"properties":{"metric":{"type":"string","description":"Dotted metric name, e.g. `container.cpu_percent` or\n`container.memory_used_bytes`."},"range":{"type":"string","description":"Time window: `1h`, `6h`, `24h`, or `7d` (defaults to `1h`)."}}},"ContainerMetricsResponse":{"type":"object","description":"Container resource metrics (CPU, memory usage)","required":["container_id","container_name","cpu_percent","memory_bytes","network_rx_bytes","network_tx_bytes","timestamp"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None = no limit."},"cpu_percent":{"type":"number","format":"double","description":"CPU usage as a multi-core percentage (Docker convention: 200 = 2 cores\nfully pinned). Divide by 100 to get cores used."},"memory_bytes":{"type":"integer","format":"int64","description":"Memory usage in bytes","minimum":0},"memory_limit_bytes":{"type":["integer","null"],"format":"int64","description":"Memory limit in bytes (if set)","minimum":0},"memory_percent":{"type":["number","null"],"format":"double","description":"Memory usage percentage (0-100) if limit is set"},"network_rx_bytes":{"type":"integer","format":"int64","description":"Network bytes received","minimum":0},"network_tx_bytes":{"type":"integer","format":"int64","description":"Network bytes transmitted","minimum":0},"timestamp":{"type":"string","description":"Timestamp of metrics collection","example":"2025-10-12T12:15:47.609192Z"}}},"ContainerResponse":{"type":"object","required":["name","container_type","can_contain_containers","can_contain_entities","metadata"],"properties":{"can_contain_containers":{"type":"boolean","description":"Can this container hold other containers?","example":true},"can_contain_entities":{"type":"boolean","description":"Can this container hold entities (tables, collections, etc.)?","example":false},"child_container_type":{"type":["string","null"],"description":"Type of child containers (if can_contain_containers is true)","example":"schema"},"container_type":{"type":"string","description":"Container type (database, schema, keyspace, bucket, etc.)","example":"database"},"entity_count_hint":{"type":["string","null"],"description":"Hint for UI on expected entity count (small = sidebar, large = pagination)","example":"large"},"entity_type_label":{"type":["string","null"],"description":"Label for entity type (if can_contain_entities is true)","example":"table"},"metadata":{"description":"Additional metadata"},"name":{"type":"string","description":"Container name","example":"mydb"}}},"ContainerRuntimeInfo":{"type":"object","description":"Snapshot of a container's lifecycle state from `docker inspect`.\n`restart_count` and `oom_killed` are the load-bearing fields when\ndiagnosing crash loops — the kernel OOM killer never reaches the\napplication's logs, so seeing `oom_killed=true` is the only signal\nthat a memory limit was the cause.","required":["role","container_name","resource_limits"],"properties":{"container_id":{"type":["string","null"],"description":"Container Docker id, when present. None = container does not exist\n(was never created or was removed externally)."},"container_name":{"type":"string","description":"Stable name of the Docker container (e.g. `postgres-mydb`)."},"exit_code":{"type":["integer","null"],"format":"int64","description":"Last container exit code, when known. Non-zero = unclean stop."},"finished_at":{"type":["string","null"],"description":"ISO-8601 timestamp of the most recent termination, when known."},"image":{"type":["string","null"],"description":"Currently-effective Docker image (e.g. `gotempsh/postgres-walg:18-bookworm`)."},"oom_killed":{"type":["boolean","null"],"description":"True when the container's last termination was caused by the\nkernel OOM killer. Set if the user enabled hard memory limits\nand the working set exceeded them."},"resource_limits":{"$ref":"#/components/schemas/ServiceResourceLimits","description":"Currently-applied resource limits read off the container's\n`HostConfig`. Compare this against the user-configured limits to\ndetect drift (an old container that never picked up new caps)."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Total restarts since the container was created. Useful for\ndetecting crash loops — a steady stream means something is killing\nthe container repeatedly (frequently OOM)."},"role":{"type":"string","description":"`service_members.role` for cluster members; \"standalone\" otherwise."},"started_at":{"type":["string","null"],"description":"ISO-8601 timestamp of when the container last started. None when\nit has never started (i.e. created but never run)."},"status":{"type":["string","null"],"description":"Bollard container state (\"running\", \"exited\", \"dead\", etc.). None\nwhen the container does not exist."}}},"ContainerStatsSample":{"type":"object","description":"Live resource usage sample for a single container.\n\n`cpu_percent` is computed by Docker's standard formula:\n ((cpu_delta / system_delta) * online_cpus) * 100\n`memory_percent` is `(memory_usage / memory_limit) * 100` — when no\nmemory limit is set the limit reported by Docker is the host's total\nRAM, so a 5% reading means \"5% of host RAM\", not \"5% of allocated\".","required":["role","container_name"],"properties":{"container_name":{"type":"string"},"cpu_percent":{"type":["number","null"],"format":"double","description":"CPU usage as a percentage. `None` when the container is not running\n(Docker returns no usable counters)."},"memory_limit_bytes":{"type":["integer","null"],"format":"int64","description":"Memory limit in bytes (host RAM if no limit set).","minimum":0},"memory_percent":{"type":["number","null"],"format":"double","description":"Memory usage as a percentage of `memory_limit_bytes`."},"memory_usage_bytes":{"type":["integer","null"],"format":"int64","description":"Resident memory usage in bytes.","minimum":0},"online_cpus":{"type":["integer","null"],"format":"int32","description":"Number of cores Docker observed at sample time. Used by the UI\nto label \"x/y cores\" instead of just a percent.","minimum":0},"role":{"type":"string"}}},"ContentPart":{"type":"object","required":["type"],"properties":{"image_url":{},"text":{"type":["string","null"]},"type":{"type":"string"}}},"ContextLine":{"type":"object","description":"A line in context response","required":["timestamp","level","message","line_offset","is_match"],"properties":{"fields":{},"is_match":{"type":"boolean","description":"Whether this line matched the original search"},"level":{"$ref":"#/components/schemas/LogLevel"},"line_offset":{"type":"integer","format":"int32"},"message":{"type":"string"},"timestamp":{"type":"string"}}},"ContextLogsRequest":{"type":"object","required":["chunk_id","line_offset"],"properties":{"chunk_id":{"type":"string"},"line_offset":{"type":"integer","format":"int32"},"lines":{"type":["integer","null"],"format":"int32","description":"Number of context lines before and after (default: 25)","minimum":0}}},"ContextLogsResponse":{"type":"object","required":["lines","target_index"],"properties":{"lines":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"}},"target_index":{"type":"integer","minimum":0}}},"ConversationDetailResponse":{"allOf":[{"$ref":"#/components/schemas/ConversationResponse"},{"type":"object","required":["messages"],"properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/MessageResponse"},"description":"Turns oldest-first. The `system` seed message is omitted (internal)."}}}]},"ConversationResponse":{"type":"object","required":["public_id","context_type","context_id","status","created_at","last_activity_at"],"properties":{"context_id":{"type":"string"},"context_type":{"type":"string"},"created_at":{"type":"string"},"last_activity_at":{"type":"string"},"public_id":{"type":"string"},"status":{"type":"string"},"title":{"type":["string","null"]}}},"ConversationSummary":{"type":"object","description":"A conversation summary grouping related AI invocations.","required":["conversation_id","message_count","total_input_tokens","total_output_tokens","total_tokens","total_cost_microcents","avg_latency_ms","models_used","first_at","last_at"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"conversation_id":{"type":"string"},"first_at":{"type":"string"},"last_at":{"type":"string"},"message_count":{"type":"integer","format":"int64"},"models_used":{"type":"array","items":{"type":"string"}},"total_cost_microcents":{"type":"integer","format":"int64"},"total_input_tokens":{"type":"integer","format":"int64"},"total_output_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"ConversationsQueryParams":{"type":"object","properties":{"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"limit":{"type":["integer","null"],"format":"int64","description":"Max results (defaults to 50, max 100)","minimum":0},"model":{"type":["string","null"],"description":"Filter by model name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"CopyBlobRequest":{"type":"object","description":"Request to copy a blob","required":["fromUrl","toPathname"],"properties":{"fromUrl":{"type":"string","description":"Source blob URL or pathname","example":"/api/blob/10/images/avatar.png"},"projectId":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"toPathname":{"type":"string","description":"Destination pathname","example":"images/avatar-copy.png"}}},"CostAnalysis":{"type":"object","description":"Full cluster cost + rightsizing analysis attached to an import plan.","required":["nodes","capacity","requested","usage_source","overprovisioning","recommendation","notes"],"properties":{"actual_usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourceFootprint","description":"Measured usage from the metrics API (`metrics.k8s.io`).\n`None` when metrics-server is not installed."}]},"capacity":{"$ref":"#/components/schemas/ClusterCapacity","description":"Total cluster capacity (sum of node allocatable resources)"},"control_plane_monthly_usd":{"type":["number","null"],"format":"double","description":"Managed control-plane fee included in `current_monthly_usd` (EKS/GKE\ncharge ~$73/mo per cluster). `None` when not applicable/unknown."},"current_monthly_usd":{"type":["number","null"],"format":"double","description":"Estimated total infrastructure cost per month in USD (compute nodes +\ncontrol-plane fee). `None` when no node could be priced."},"nodes":{"type":"array","items":{"$ref":"#/components/schemas/NodeCostInfo"},"description":"Per-node inventory with price estimates where the instance type is known"},"notes":{"type":"array","items":{"type":"string"},"description":"Honesty notes: what could not be measured, which numbers are\nestimates, and any assumptions made. Always shown to the user."},"overprovisioning":{"$ref":"#/components/schemas/OverprovisioningAssessment","description":"Requests-vs-capacity-vs-usage assessment"},"provider":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CloudProvider","description":"Detected cloud provider (from node `providerID` prefixes)"}]},"recommendation":{"$ref":"#/components/schemas/TargetRecommendation","description":"The temps/Hetzner target sizing and savings estimate"},"requested":{"$ref":"#/components/schemas/ResourceFootprint","description":"Sum of pod resource *requests* across running pods — what the\nscheduler has reserved, i.e. what the cluster is sized for."},"usage_source":{"$ref":"#/components/schemas/UsageSource","description":"How the usage numbers were obtained (drives UI wording)"}}},"CreateAlertRuleRequest":{"type":"object","required":["name","trigger_type"],"properties":{"cooldown_minutes":{"type":"integer","format":"int32","description":"Minimum minutes between notifications for same rule+group"},"enabled":{"type":"boolean"},"environment_filter":{"type":["integer","null"],"format":"int32","description":"Optional environment ID to filter alerts"},"error_level_filter":{"type":["string","null"],"description":"Optional error type/level filter"},"name":{"type":"string"},"notification_priority":{"type":"string","description":"Notification priority: Low, Normal, High, Critical"},"trigger_config":{"description":"Trigger-specific configuration (e.g., {\"count\": 100, \"window_minutes\": 60} for frequency)"},"trigger_type":{"type":"string","description":"Trigger type: new_issue, regression, frequency, new_user, user_count, status_change"}}},"CreateApiKeyRequest":{"type":"object","required":["name","role_type"],"properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["projects:read","deployments:read"]},"role_type":{"type":"string","example":"admin"}}},"CreateApiKeyResponse":{"type":"object","required":["id","name","key_prefix","role_type","api_key","created_at"],"properties":{"api_key":{"type":"string"},"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"key_prefix":{"type":"string"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"role_type":{"type":"string"}}},"CreateBackupScheduleRequest":{"type":"object","required":["name","backup_type","retention_period","schedule_expression","enabled","tags"],"properties":{"backup_type":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"include_control_plane":{"type":["boolean","null"],"description":"When `true` (default), every run also produces a `control_plane`\nbackup of Temps's own database. Operators who use Temps purely as\na backup orchestrator for external DBs can set this to `false` to\nkeep the run history focused on those services."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Optional wall-clock timeout override for jobs created by this schedule\n(seconds). When set, overrides the engine-family default. `null` means\n\"use engine default.\" The per-job `max_runtime_secs` in\n`EnqueueJobParams` can still override this for ad-hoc triggers."},"name":{"type":"string"},"retention_period":{"type":"integer","format":"int32"},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"Optional S3 source. If omitted, the current default S3 source is used."},"schedule_expression":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"target_all_services":{"type":["boolean","null"],"description":"When `true` (default), the schedule backs up every external service\non the host — including databases created in the future. When\n`false`, the schedule backs up only the services explicitly attached\nvia `POST /backups/schedules/{id}/services`. Omit to use the default."}}},"CreateBitbucketRequest":{"type":"object","required":["name","auth"],"properties":{"auth":{"$ref":"#/components/schemas/BitbucketAuthInput","description":"Authentication credentials — either an access token or an app password."},"name":{"type":"string","description":"Display name for this provider."}}},"CreateCloudflareProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/CloudflareConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateConversationRequest":{"type":"object","required":["context_type","context_id"],"properties":{"context_id":{"type":"string","description":"The entity id (ints stringified)."},"context_type":{"type":"string","description":"e.g. `\"deployment\"`."}}},"CreateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"name":{"type":["string","null"]}}},"CreateDashboardRequest":{"type":"object","required":["project_id","name","layout"],"properties":{"layout":{"$ref":"#/components/schemas/DashboardLayout"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"}}},"CreateDeploymentTokenRequest":{"type":"object","required":["name"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment ID - if set, token is scoped to a specific deployment"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID - if not set, token applies to all environments"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"},"description":"List of permissions (e.g., [\"visitors:enrich\", \"emails:send\"])\nIf not provided, defaults to full access","example":["visitors:enrich","emails:send"]}}},"CreateDeploymentTokenResponse":{"type":"object","required":["id","project_id","name","token_prefix","token","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"project_id":{"type":"integer","format":"int32"},"token":{"type":"string","description":"The full token value - only returned on creation"},"token_prefix":{"type":"string"}}},"CreateDnsProviderRequest":{"type":"object","description":"Request to create a new DNS provider","required":["name","provider_type","credentials"],"properties":{"credentials":{"$ref":"#/components/schemas/DnsProviderCredentials","description":"Provider credentials"},"description":{"type":["string","null"],"description":"Optional description"},"name":{"type":"string","description":"User-friendly name","example":"My Cloudflare"},"provider_type":{"$ref":"#/components/schemas/DnsProviderType","description":"Provider type"}}},"CreateDomainRequest":{"type":"object","required":["domain"],"properties":{"challenge_type":{"type":"string","description":"Challenge type for Let's Encrypt validation. Options: \"http-01\" (default) or \"dns-01\""},"domain":{"type":"string"}}},"CreateEmailDomainRequest":{"type":"object","required":["provider_id","domain"],"properties":{"domain":{"type":"string","description":"Domain name (e.g., \"updates.example.com\")","example":"updates.example.com"},"provider_id":{"type":"integer","format":"int32","description":"Provider ID to use for this domain"}}},"CreateEmailProviderRequest":{"type":"object","required":["name","provider_type","region"],"properties":{"name":{"type":"string","description":"User-friendly name for the provider","example":"My AWS SES"},"provider_type":{"$ref":"#/components/schemas/EmailProviderTypeRoute","description":"Provider type"},"region":{"type":"string","description":"Cloud region. For SMTP this is informational only — the host/port carry the real routing.","example":"us-east-1"},"scaleway_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ScalewayCredentialsRequest","description":"Scaleway credentials (required if provider_type is scaleway)"}]},"ses_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SesCredentialsRequest","description":"AWS SES credentials (required if provider_type is ses)"}]},"smtp_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SmtpCredentialsRequest","description":"Generic SMTP credentials (required if provider_type is smtp). Use when\nyou only have SMTP creds and want to import an already-set-up domain."}]},"sns_topic_arn":{"type":["string","null"],"description":"Exact SNS topic allowed to deliver SES events for this provider."}}},"CreateEnvironmentRequest":{"type":"object","required":["name","branch"],"properties":{"branch":{"type":"string"},"name":{"type":"string"},"set_as_preview":{"type":"boolean","description":"If true, set this environment as the preview environment for the project"}}},"CreateEnvironmentVariableRequest":{"type":"object","required":["key","value","environment_ids"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean","description":"Include this environment variable in preview environments (default: true)"},"is_secret":{"type":"boolean","description":"When true the variable is treated as write-only: never returned in\nplaintext from the API, masked in the UI, and updates that omit the\nvalue preserve the existing ciphertext. The flag is one-way — secret\nvars cannot be demoted back to regular vars."},"key":{"type":"string"},"value":{"type":"string"}}},"CreateExternalServiceRequest":{"type":"object","required":["name","service_type","parameters"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberRequest"},"description":"Cluster member specifications. Required when topology is \"cluster\"."},"name":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Target node ID for the service. Omit or null to run on the control plane."},"parameters":{"type":"object","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"},"topology":{"type":"string","description":"Service topology: \"standalone\" (default) or \"cluster\" (HA multi-member).","example":"standalone"},"version":{"type":["string","null"]}}},"CreateFlagRequest":{"type":"object","required":["key","value_type","default_value"],"properties":{"client_visible":{"type":"boolean","description":"Whether the flag may be exposed on the unauthenticated same-origin\nevaluation endpoint. Defaults to `false`: flags are server-only unless\nexplicitly opted in, because targeting rules can encode business logic."},"default_value":{"description":"Served whenever evaluation cannot do better. Must match `value_type`.\n\nLeft unannotated so utoipa emits a free-form schema: a bool flag's\ndefault is `false`, not an object, and `value_type = Object` would tell\nevery generated client otherwise."},"description":{"type":["string","null"]},"key":{"type":"string","description":"Stable key used in application code. Immutable after create.","example":"checkout.v2"},"value_type":{"$ref":"#/components/schemas/FlagValueType","description":"Fixed at create: retyping would invalidate every stored value and every\ncall site."}}},"CreateFunnelRequest":{"type":"object","required":["name","steps"],"properties":{"description":{"type":["string","null"]},"name":{"type":"string"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/CreateFunnelStep"}}}},"CreateFunnelResponse":{"type":"object","required":["funnel_id","message"],"properties":{"funnel_id":{"type":"integer","format":"int32"},"message":{"type":"string"}}},"CreateFunnelStep":{"type":"object","required":["event_name"],"properties":{"event_filter":{"type":"array","items":{"$ref":"#/components/schemas/SmartFilter"}},"event_name":{"type":"string"}}},"CreateGenericRequest":{"type":"object","required":["name","clone_url"],"properties":{"base_url":{"type":["string","null"],"description":"Optional base URL of the git host for display purposes (no API is called)."},"clone_url":{"type":"string","description":"HTTPS clone URL for the repository, e.g. `https://git.example.com/org/repo.git`."},"name":{"type":"string","description":"Display name for this provider."},"token":{"type":["string","null"],"description":"Access token or password. Omit (or set to `null`) for public repositories."},"token_username":{"type":["string","null"],"description":"HTTP Basic username used with the token. Defaults to `x-access-token` when\nabsent or empty. Ignored for public (unauthenticated) repositories."}}},"CreateGitHubPATRequest":{"type":"object","required":["name","token"],"properties":{"name":{"type":"string"},"token":{"type":"string"}}},"CreateGitLabOAuthRequest":{"type":"object","required":["name","client_id","client_secret","redirect_uri"],"properties":{"base_url":{"type":["string","null"]},"client_id":{"type":"string"},"client_secret":{"type":"string"},"name":{"type":"string"},"redirect_uri":{"type":"string"}}},"CreateGitLabPATRequest":{"type":"object","required":["name","token"],"properties":{"base_url":{"type":["string","null"]},"name":{"type":"string"},"token":{"type":"string"}}},"CreateGiteaPATRequest":{"type":"object","required":["name","token","base_url"],"properties":{"base_url":{"type":"string","description":"HTTPS base URL of the Gitea instance, e.g. `https://git.example.com`."},"name":{"type":"string","description":"Display name for this provider."},"token":{"type":"string","description":"Personal access token issued by the Gitea instance."}}},"CreateIncidentRequest":{"type":"object","required":["title","severity"],"properties":{"description":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"monitor_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"title":{"type":"string"}}},"CreateIntegrationBody":{"type":"object","required":["provider","signing_secret"],"properties":{"provider":{"type":"string","description":"Registered provider name, e.g. \"stripe\"."},"signing_secret":{"type":"string","description":"Signing secret from the provider's dashboard."}}},"CreateIpAccessControlRequest":{"type":"object","description":"Request to create an IP access control rule","required":["ip_address","action"],"properties":{"action":{"type":"string","description":"Action to take: \"block\" or \"allow\"","example":"block"},"ip_address":{"type":"string","description":"IP address in CIDR notation (e.g., \"192.168.1.1\" or \"10.0.0.0/24\")","example":"192.168.1.100"},"reason":{"type":["string","null"],"description":"Optional reason for the action","example":"Malicious activity detected"}}},"CreateMcpRequest":{"type":"object","required":["slug","name","config"],"properties":{"config":{"type":"object"},"description":{"type":["string","null"]},"name":{"type":"string"},"slug":{"type":"string"}}},"CreateMetricAlertRequest":{"type":"object","required":["project_id","name","metric_name","aggregation","detection_config","window_secs","for_duration_secs","severity","enabled"],"properties":{"aggregation":{"type":"string","description":"One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"The detector: a discriminated union keyed by `kind`. Today only\n`{ \"kind\": \"static\", \"comparator\": \"gt\", \"threshold\": 500 }` is evaluable."},"dynamic_alerts":{"type":"boolean","description":"When true (and `group_by` is set) fire one independent alarm per breaching\nseries. Static detectors only. Default false."},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32"},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys to break the metric down by, e.g. `[\"endpoint\",\"region\"]`. Empty\n(the default) = one aggregate stream. Max 2 keys; keys must match\n`[a-zA-Z0-9_.:-]`."},"grouped_notification_threshold":{"type":"integer","format":"int32","description":"When more than this many series transition to firing in the same tick, only\nthe first gets the expensive chart/AI enrichment. Range 1–1000, default 5."},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters: `[[\"key\",\"value\"],…]`. Empty = no\nfiltering (the default). Max 10 pairs; keys must match `[a-zA-Z0-9_.:-]`;\nvalues capped at 500 characters."},"max_series":{"type":"integer","format":"int32","description":"Cardinality cap for dynamic alerting: at most this many series (top by\n`|value|`). Range 1–100, default 20."},"metric_name":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"severity":{"type":"string","description":"One of `info|warning|critical`."},"window_secs":{"type":"integer","format":"int32"}}},"CreateMonitorRequest":{"type":"object","required":["name","monitor_type","environment_id"],"properties":{"check_interval_seconds":{"type":["integer","null"],"format":"int32"},"check_path":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"monitor_type":{"type":"string"},"name":{"type":"string"}}},"CreateNotificationEmailProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/EmailConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateOidcProviderRequest":{"type":"object","required":["name","issuer_url","client_id","client_secret"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"default_role":{"type":"string"},"enabled":{"type":"boolean"},"group_claim":{"type":"string"},"issuer_url":{"type":"string"},"jit_provisioning":{"type":"boolean"},"name":{"type":"string"},"role_claim":{"type":"string"},"scopes":{"type":"string"},"template":{"type":"string"},"trust_idp_email":{"type":"boolean","description":"Defaults false. Set to true only for IdPs where an admin\ncontrols user provisioning (corporate Okta, Azure AD) and\nself-signup of arbitrary emails is not possible — see the\n`trust_idp_email` field on `oidc_providers::Model` for the\nsecurity tradeoff this enables."}}},"CreateOidcRoleMappingRequest":{"type":"object","required":["priority","idp_group","role"],"properties":{"idp_group":{"type":"string"},"priority":{"type":"integer","format":"int32"},"role":{"type":"string"}}},"CreatePlanRequest":{"type":"object","description":"Request to create an import plan","required":["source","workload_id"],"properties":{"credentials":{"$ref":"#/components/schemas/ImportCredentials","description":"Platform credentials (required for cloud platforms like Vercel, Railway)"},"repository_id":{"type":["integer","null"],"format":"int32","description":"Optional repository ID to associate with the import\nIf provided, preset will be detected from the repository"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source to import from"},"workload_id":{"$ref":"#/components/schemas/WorkloadId","description":"Workload ID to import"}}},"CreatePlanResponse":{"type":"object","description":"Response with created plan","required":["session_id","plan","validation","can_execute"],"properties":{"can_execute":{"type":"boolean","description":"Whether the plan can be executed"},"plan":{"$ref":"#/components/schemas/ImportPlan","description":"Generated import plan"},"session_id":{"type":"string","description":"Session ID for tracking"},"validation":{"$ref":"#/components/schemas/ValidationReport","description":"Validation report"}}},"CreatePrResponse":{"type":"object","required":["run","pr_url","pr_number","branch_name"],"properties":{"branch_name":{"type":"string"},"pr_number":{"type":"integer","format":"int32"},"pr_url":{"type":"string"},"run":{"$ref":"#/components/schemas/AutofixerRunResponse"}}},"CreateProjectFromTemplateRequest":{"type":"object","description":"Request to create a project from a template\n\nSupports two deploy modes:\n * **Fork mode** — when `git_provider_connection_id` is set, the template\n repo is cloned into a new repository under the user's Git account and the\n project tracks that fork (git-push deploys, automatic deploy on push).\n * **One-click public-repo mode** — when `git_provider_connection_id` is\n omitted, the project deploys directly from the template's public source\n repository (no fork, no Git account required). This is the activation\n path: a brand-new user with no Git provider connected can still deploy a\n demo in one click. `repository_name` / `repository_owner` are ignored in\n this mode, and automatic-deploy-on-push is unavailable (there is no fork\n to receive webhooks).","required":["template_slug","project_name"],"properties":{"automatic_deploy":{"type":"boolean","description":"Enable automatic deployment on push (defaults to true). Only honoured in\nfork mode; public-repo deploys cannot receive push webhooks."},"environment_variables":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarInput"},"description":"Environment variables to set (key-value pairs)"},"git_provider_connection_id":{"type":["integer","null"],"format":"int32","description":"Git provider connection ID. When omitted, the project deploys directly\nfrom the template's public source repository instead of forking it."},"private":{"type":"boolean","description":"Whether to make the repository private (defaults to true)"},"project_name":{"type":"string","description":"Name for the new project"},"repository_name":{"type":["string","null"],"description":"Name for the new repository to create. Required in fork mode; ignored in\none-click public-repo mode."},"repository_owner":{"type":["string","null"],"description":"Owner/organization for the new repository (defaults to authenticated user)"},"storage_service_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"External storage service IDs to attach to the project"},"template_slug":{"type":"string","description":"Template slug to use as the base"}}},"CreateProjectFromTemplateResponse":{"type":"object","description":"Response after creating a project from template","required":["project_id","project_slug","project_name","repository_url","template_slug","message"],"properties":{"message":{"type":"string","description":"Message with additional info"},"project_id":{"type":"integer","format":"int32","description":"ID of the created project"},"project_name":{"type":"string","description":"Name of the created project"},"project_slug":{"type":"string","description":"Slug of the created project"},"repository_url":{"type":"string","description":"URL of the created repository"},"template_slug":{"type":"string","description":"Template that was used"}}},"CreateProjectRequest":{"type":"object","required":["name","directory","main_branch","preset","storage_service_ids"],"properties":{"automatic_deploy":{"type":["boolean","null"]},"build_command":{"type":["string","null"]},"custom_domain":{"type":["string","null"]},"directory":{"type":"string"},"environment_variables":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]}},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container (fallback when image has no EXPOSE directive)\n\nPriority order for port resolution:\n1. Image EXPOSE directive (auto-detected from built image)\n2. Environment-level exposed_port (overrides this value per environment)\n3. This project-level exposed_port (fallback)\n4. Default: 3000\n\nOnly set this if your image doesn't use EXPOSE directive.","example":8080},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"]},"install_command":{"type":["string","null"]},"is_on_demand":{"type":["boolean","null"]},"is_public_repo":{"type":["boolean","null"]},"is_web_app":{"type":["boolean","null"]},"main_branch":{"type":"string"},"name":{"type":"string"},"output_dir":{"type":["string","null"]},"performance_metrics_enabled":{"type":"boolean"},"preset":{"type":"string"},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration\n\nDifferent presets accept different configuration options:\n- **Dockerfile preset**: Accepts `DockerfilePresetConfig` with `dockerfile_path` and `build_context`\n- **Nixpacks preset**: Accepts ordered `providers` (for example `[\"...\", \"python\"]`)\n and optional inline `nixpacksConfig` TOML\n- **Static presets** (Vite, Next.js, etc.): Accept `StaticPresetConfig` with build commands and output dir\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"project_type":{"type":["string","null"]},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"source_type":{"$ref":"#/components/schemas/SourceType","description":"Source type for deployments\n\nDetermines how the project is deployed:\n- **git** (default): Traditional Git-based deployments - source code is pulled, built, and deployed\n- **docker_image**: Deploy pre-built Docker images from external registries (DockerHub, GHCR, etc.)\n- **static_files**: Deploy pre-built static files uploaded as tar.gz or zip bundles\n\nFor `docker_image` and `static_files` source types, `repo_name` and `repo_owner` are optional."},"storage_service_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"use_default_wildcard":{"type":["boolean","null"]}}},"CreateProjectSecretRequest":{"type":"object","description":"Request to create a new project secret.\n\nProject secrets are mounted into the container as files under\n`/run/secrets/` (mode 0400, tmpfs) instead of as environment variables.\nValues are always encrypted at rest and never returned in plaintext from\nthe API after create. Distinct from agent secrets (global `/settings/secrets`).","required":["key","value"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean","description":"Include this secret in preview environments."},"key":{"type":"string","description":"Identifier for the secret. Becomes the filename at `/run/secrets/`.\nMust start with a letter or underscore and contain only A-Z, a-z, 0-9, _."},"value":{"type":"string","description":"Plaintext value, <= 1 MiB."}}},"CreateProviderKeyRequest":{"type":"object","required":["provider","display_name","api_key"],"properties":{"api_key":{"type":"string"},"base_url":{"type":["string","null"]},"default_model":{"type":["string","null"],"description":"Optional model id to pin for this provider (e.g. \"gpt-4o-mini\")."},"display_name":{"type":"string"},"provider":{"type":"string"}}},"CreateProviderRequest":{"type":"object","required":["name","provider_type","config"],"properties":{"config":{},"enabled":{"type":["boolean","null"]},"name":{"type":"string"},"provider_type":{"type":"string"}}},"CreateRouteRequest":{"type":"object","required":["domain","host","port"],"properties":{"domain":{"type":"string"},"host":{"type":"string"},"port":{"type":"integer","format":"int32"},"route_type":{"type":["string","null"],"description":"Route type: \"http\" (default) matches on HTTP Host header,\n\"tls\" matches on TLS SNI hostname for TCP passthrough"}}},"CreateS3SourceRequest":{"type":"object","required":["name","bucket_name","bucket_path","access_key_id","secret_key","region"],"properties":{"access_key_id":{"type":"string"},"bucket_name":{"type":"string"},"bucket_path":{"type":"string"},"endpoint":{"type":["string","null"],"description":"Optional endpoint URL for S3-compatible services like MinIO","example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"],"description":"Whether to use path-style addressing (default: true)","example":true},"is_default":{"type":["boolean","null"],"description":"When true, make this the default source (will swap out any existing default).\nThe very first S3 source is always created as default regardless of this flag.","example":false},"name":{"type":"string"},"region":{"type":"string"},"secret_key":{"type":"string"}}},"CreateSandboxBody":{"type":"object","properties":{"_runtime":{"type":["string","null"]},"backend":{"type":["string","null"],"description":"Isolation backend: `\"docker\"` (default) or `\"firecracker\"` (ADR-029,\nhardware-virtualized microVM — requires a host provisioned with\n`temps firecracker setup`). Omit for the platform default; existing\nclients are unaffected. Requesting an unavailable backend fails with\n400 rather than silently downgrading isolation."},"cpu_limit":{"type":["number","null"],"format":"double"},"disk_size_mb":{"type":["integer","null"],"format":"int64","description":"Root disk size in MB (Firecracker only; Docker ignores it). Omit for\nthe platform default (1 GiB).","minimum":0},"env":{"type":"object","description":"Extra env vars baked into the container on create.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"image":{"type":["string","null"],"description":"Docker image override. `null` uses the platform default."},"memory_limit_mb":{"type":["integer","null"],"format":"int64","minimum":0},"name":{"type":["string","null"]},"networkPolicy":{},"pids_limit":{"type":["integer","null"],"format":"int64"},"ports":{"type":"array","items":{"type":"integer","format":"int32","minimum":0},"description":"Ports the sandbox will listen on. Each port becomes a `routes[]`\nentry in the create/get response so `@vercel/sandbox`'s\n`sandbox.domain(port)` can resolve it client-side without an\nextra round-trip."},"preview_password":{"type":["string","null"],"description":"Optional preview-URL password. When set, every preview URL served\nfor this sandbox is gated behind a login form. 8–256 characters.\nOmit to leave preview URLs open (the sandbox ID remains the only\ngate). The plaintext is never returned; only the last-4 hint is\nsurfaced in `SandboxResponse.preview_password_hint`."},"projectId":{"type":["string","null"]},"resources":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourcesBody","description":"`@vercel/sandbox`'s nested resources object. When present, its\n`memory` / `vcpus` populate `memory_limit_mb` / `cpu_limit` if those\nweren't sent directly."}]},"source":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SourceBody","description":"Optional initial content to seed into the work dir. Clones a\nrepo or extracts a tarball after the sandbox is created."}]},"timeout":{"type":["integer","null"],"format":"int64","description":"Idle timeout as sent by `@vercel/sandbox` (milliseconds). Converted\nto seconds when `timeout_secs` is absent.","minimum":0},"timeout_secs":{"type":["integer","null"],"format":"int64","description":"Idle timeout in seconds (temps-native). Clamped to `[60, 86400]`.","minimum":0}}},"CreateSkillRequest":{"type":"object","required":["slug","name","content"],"properties":{"content":{"type":"string"},"description":{"type":["string","null"]},"name":{"type":"string"},"slug":{"type":"string"}}},"CreateSlackProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/SlackConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateUserRequest":{"type":"object","required":["username","roles"],"properties":{"email":{"type":["string","null"]},"password":{"type":["string","null"]},"roles":{"type":"array","items":{"type":"string"}},"username":{"type":"string"}}},"CreateWebhookProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/WebhookConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateWebhookRequestBody":{"type":"object","required":["url","events"],"properties":{"enabled":{"type":["boolean","null"],"description":"Whether the webhook is enabled","default":true},"events":{"type":"array","items":{"type":"string"},"description":"Event types to subscribe to","example":["deployment.created","deployment.succeeded"]},"secret":{"type":["string","null"],"description":"Secret for HMAC signature verification (optional)"},"url":{"type":"string","description":"Target URL for webhook delivery","example":"https://example.com/webhook"}}},"CreatedResource":{"type":"object","description":"Resource created during import (for rollback / audit)","required":["resource_type","resource_id","resource_name"],"properties":{"resource_id":{"type":"integer","format":"int32","description":"Resource ID"},"resource_name":{"type":"string","description":"Resource name"},"resource_type":{"type":"string","description":"Resource type (project, environment, deployment, service, domain, etc.)"}}},"CronExecutionInfo":{"type":"object","required":["id","cron_id","executed_at","url","status_code","headers","response_time_ms"],"properties":{"cron_id":{"type":"integer","format":"int32"},"error_message":{"type":["string","null"]},"executed_at":{"type":"string"},"headers":{"type":"string"},"id":{"type":"integer","format":"int32"},"response_time_ms":{"type":"integer","format":"int32"},"status_code":{"type":"integer","format":"int32"},"url":{"type":"string"}}},"CronInfo":{"type":"object","required":["id","project_id","environment_id","path","schedule","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"deleted_at":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"next_run":{"type":["string","null"]},"path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"schedule":{"type":"string"},"updated_at":{"type":"string"}}},"CrossProjectSiblingRef":{"type":"object","description":"A sibling project that shares the same `trace_id`, returned by the\nPhase 1 cross-project banner endpoint.","required":["project_id","project_name","project_slug","first_seen"],"properties":{"first_seen":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC, `Z` suffix) of first span ingest for this\n`(trace_id, project_id)` pair."},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the sibling project's single-project trace view."}}},"CrossProjectTraceResponse":{"type":"object","description":"Response body for `GET /otel/traces/cross-project/{trace_id}`.\n\nAn empty `siblings` vec is the normal single-project case — never 404.","required":["trace_id","siblings"],"properties":{"siblings":{"type":"array","items":{"$ref":"#/components/schemas/CrossProjectSiblingRef"},"description":"Projects other than the caller's that hold spans for this trace,\nordered by `first_seen ASC`."},"trace_id":{"type":"string","description":"The trace_id that was queried (echoed back for client convenience)."}}},"CurrentStatusResponse":{"type":"object","required":["monitor_id","current_status","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["number","null"],"format":"double"},"current_status":{"type":"string"},"last_check_at":{"type":["string","null"],"format":"date-time"},"monitor_id":{"type":"integer","format":"int32"},"uptime_percentage":{"type":"number","format":"double"}}},"CustomDomainRequest":{"type":"object","required":["domain","environment_id"],"properties":{"branch":{"type":["string","null"]},"domain":{"type":"string"},"environment_id":{"type":"integer","format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to (only for docker-compose projects)"},"status_code":{"type":["integer","null"],"format":"int32"}}},"CustomDomainResponse":{"type":"object","required":["id","project_id","domain","status","created_at","updated_at"],"properties":{"branch":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"domain_id":{"type":["integer","null"],"format":"int32"},"environment":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DomainEnvironmentResponse"}]},"expiration_time":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"last_renewed":{"type":["integer","null"],"format":"int64"},"message":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to"},"status":{"type":"string"},"status_code":{"type":["integer","null"],"format":"int32"},"updated_at":{"type":"integer","format":"int64"}}},"CustomerMovementResponse":{"type":"object","required":["bucket","new_customers","churned_customers"],"properties":{"bucket":{"type":"string","format":"date-time"},"churned_customers":{"type":"integer","format":"int64"},"new_customers":{"type":"integer","format":"int64"}}},"DashboardLayout":{"type":"object","description":"The typed layout persisted (as JSONB) in `metric_dashboards.layout`.","required":["sections"],"properties":{"sections":{"type":"array","items":{"$ref":"#/components/schemas/DashboardSection"},"description":"Ordered sections that make up the dashboard."}}},"DashboardProjectsAnalyticsQuery":{"type":"object","description":"Query parameters for batch dashboard analytics","required":["project_ids","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"project_ids":{"type":"string","description":"Comma-separated list of project IDs"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"DashboardProjectsAnalyticsResponse":{"type":"object","description":"Batch response for dashboard project analytics","required":["projects"],"properties":{"projects":{"type":"object","description":"Map of project_id -> analytics data","additionalProperties":{"$ref":"#/components/schemas/ProjectDashboardAnalytics"},"propertyNames":{"type":"string"}}}},"DashboardSection":{"type":"object","description":"A titled group of tiles within a dashboard.","required":["id","title","tiles"],"properties":{"id":{"type":"string","description":"Stable client-generated section id."},"tiles":{"type":"array","items":{"$ref":"#/components/schemas/DashboardTile"},"description":"Tiles rendered within this section."},"title":{"type":"string","description":"Section heading."}}},"DashboardTile":{"type":"object","description":"A single metric tile within a dashboard section.","required":["id","metric_name","aggregation"],"properties":{"aggregation":{"type":"string","description":"Aggregation applied per bucket: one of\n`avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys to break the metric down by (group-by / multi-series view).\nEmpty = single aggregated series (current behavior). Max 2 keys — more\ndimensions are unreadable in a chart (ADR-026 Phase 2). Each key must\nmatch `[a-zA-Z0-9_.:-]`. Wired directly to `MetricQuery.group_by` by\nthe tile query path (separate frontend task)."},"id":{"type":"string","description":"Stable client-generated tile id (used as a React key / for reordering)."},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters: `[[\"key\",\"value\"],…]`. Empty = no\nfiltering. Max 10 pairs; keys must match `[a-zA-Z0-9_.:-]`; values\ncapped at 500 characters. Not yet wired into the tile query path\n(Phase 1 ADR-026 — field round-trips and validates; query wiring is\na separate frontend task)."},"metric_name":{"type":"string","description":"The metric name to chart (e.g. `http.server.duration`)."},"title":{"type":["string","null"],"description":"Optional display title; falls back to the metric name in the UI."}}},"DataImplication":{"type":"object","description":"A specific data implication the user needs to understand","required":["severity","message"],"properties":{"message":{"type":"string","description":"Human-readable description of what could happen"},"recommended_action":{"type":["string","null"],"description":"What the user should do about it (if anything)"},"severity":{"$ref":"#/components/schemas/DataImplicationSeverity","description":"Severity of this implication"}}},"DataImplicationSeverity":{"type":"string","description":"Severity of a data implication","enum":["info","warning","data-not-migrated","potential-data-loss"]},"DatabaseMetricsResponse":{"type":"object","description":"Response for the per-database metrics breakdown.","required":["databases"],"properties":{"databases":{"type":"array","items":{"$ref":"#/components/schemas/DatabaseMetricsRow"},"description":"One entry per database, sorted by the first metric descending\n(largest first) so the biggest database leads the table."}}},"DatabaseMetricsRow":{"type":"object","description":"Per-database metric values for a Postgres service.\n\nA Postgres instance can host many databases (some unrelated to this\nservice). The collector records per-`datname` series; this groups the\nlatest value of each requested metric by database so the UI can render a\n\"Databases\" breakdown table instead of one collapsed number.","required":["database","metrics"],"properties":{"database":{"type":"string","description":"Database name (`datname`)."},"metrics":{"type":"object","description":"Latest value of each requested metric for this database\n(e.g. `{\"pg.database_size_bytes\": 7943871, \"pg.cache_hit_ratio\": 0.99}`).","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}},"DelRequest":{"type":"object","description":"Request to delete keys","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"},"description":"The key(s) to delete","example":["user:123","user:456"]},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"DelResponse":{"type":"object","description":"Response for delete operation","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","description":"Number of keys deleted","example":2}}},"DeleteBlobRequest":{"type":"object","description":"Request to delete blobs","required":["pathnames"],"properties":{"pathnames":{"type":"array","items":{"type":"string"},"description":"Pathnames to delete (relative to project)","example":["images/avatar.png","documents/file.pdf"]},"projectId":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"DeleteBlobResponse":{"type":"object","description":"Response after deleting blobs","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","description":"Number of blobs deleted","example":2}}},"DeleteResponse":{"type":"object","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","minimum":0}}},"DeployFromImageRequest":{"type":"object","properties":{"external_image_id":{"type":["integer","null"],"format":"int32","description":"External image ID (if already registered). If provided without image_ref,\nthe image reference will be fetched from the registered external image."},"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nImage deploys can't read `.temps.yaml`, so this sets the path the deployer\nprobes after the container starts and the path the environment's uptime\nmonitor checks. Must start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"image_ref":{"type":["string","null"],"description":"Docker image reference (e.g., \"ghcr.io/org/app:v1.0\")\nRequired if external_image_id is not provided","example":"ghcr.io/myorg/myapp:v1.0"},"metadata":{"description":"Optional deployment metadata"}}},"DeployFromImageUploadQuery":{"type":"object","description":"Query parameters for deploying from an uploaded image tarball","properties":{"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nMust start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"tag":{"type":["string","null"],"description":"Tag to apply to the imported image (e.g., \"myapp:v1.0\")\nIf not provided, a unique tag will be generated","example":"myapp:v1.0"}}},"DeployFromStaticRequest":{"type":"object","required":["static_bundle_id"],"properties":{"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nStatic deploys can't read `.temps.yaml`, so this sets the path the deployer\nprobes after the container starts and the path the environment's uptime\nmonitor checks. Must start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"metadata":{"description":"Optional deployment metadata"},"static_bundle_id":{"type":"integer","format":"int32","description":"Static bundle ID (required)"}}},"DeploymentConfig":{"type":"object","description":"Deployment configuration shared between projects and environments\n\nThis configuration can be set at the project level (as defaults) and\noverridden at the environment level for specific deployments.\n\nNote: Environment variables are managed separately and are not part of this config.","properties":{"antiAffinity":{"type":"boolean","description":"Anti-affinity: spread replicas across different nodes.\n\nWhen enabled, the scheduler avoids placing two replicas of the same\nenvironment on the same node. If there are fewer eligible nodes than\nreplicas, remaining replicas wrap around (best-effort spreading).\n\nDefaults to `true` — replicas spread by default."},"automaticDeploy":{"type":["boolean","null"],"description":"Enable automatic deployments on git push.\n`None` = inherit from project config; `Some(true/false)` = explicit override.\nStored as JSONB so absent key → `None` (inherit), never silently defaults to false."},"containerExecEnabled":{"type":"boolean","description":"Enable container exec/shell access (disabled by default for security)"},"cpuLimit":{"type":["integer","null"],"format":"int32","description":"CPU limit in microcores, where 1_000_000 = 1 full CPU core\n(e.g., 2_000_000 = 2 CPUs). NOT millicores. `None` = uncapped."},"cpuRequest":{"type":["integer","null"],"format":"int32","description":"CPU request in microcores, where 1_000_000 = 1 full CPU core\n(e.g., 100_000 = 0.1 CPU, 500_000 = 0.5 CPU, 2_000_000 = 2 CPUs).\nNOT millicores — the deployer formats this as `{n}u` and converts\n`n / 1_000_000` cores into Docker nano_cpus."},"crossArchitectureBuilds":{"type":["boolean","null"],"description":"Build one image per architecture the eligible nodes run.\n\n`None`/`false` (the default) builds exactly once, on the control\nplane's native platform — byte-for-byte the behaviour of a\nsingle-architecture cluster. When enabled and the nodes this\ndeployment could land on span more than one architecture, the build\njob produces one image per architecture; the non-native ones go\nthrough the daemon's `platform` option, which requires QEMU binfmt\nhandlers registered on the control plane.\n\n**Opt-in on purpose.** Cross-architecture builds are emulated and\nsubstantially slower, and deriving them from cluster topology would\nmean a single node joining silently changes build behaviour for every\ndeployment in the cluster. It also keeps the decision on operator\nconfig rather than on a value each node reports about itself.\n\n`Option` so an environment inherits the project's setting\n(`None`) or overrides it, matching `automatic_deploy`."},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container\nIf not specified, will be auto-detected from Docker image or default to 3000"},"idleTimeoutSeconds":{"type":"integer","format":"int32","description":"Seconds of inactivity before containers are stopped in on-demand mode.\nOnly used when `on_demand` is true. Min: 60, Max: 86400 (24h).\nDefault: 300 (5 minutes)."},"memoryLimit":{"type":["integer","null"],"format":"int32","description":"Memory limit in megabytes. Three-state semantics:\n- `None` → inherit the parent layer (env inherits project, project\n inherits the seeded default); used by the settings UI's \"Use default\".\n- `Some(0)` → explicit **uncapped**: stop inheriting and run with no\n memory limit. This is the deliberate escape hatch for dedicated\n workloads, distinct from `None`.\n- `Some(n)` → hard cap of `n` MB.\n\n`merge`/resolution keep `Some(0)` as a present value (it wins precedence\nover a parent cap), and the deployer collapses it to \"no limit\" before\ntalking to Docker."},"memoryRequest":{"type":["integer","null"],"format":"int32","description":"Memory request in megabytes (e.g., 128 = 128MB)"},"onDemand":{"type":"boolean","description":"Enable on-demand mode (scale-to-zero).\nWhen enabled, containers are stopped after `idle_timeout_seconds` of no traffic\nand automatically started when a new request arrives."},"performanceMetricsEnabled":{"type":"boolean","description":"Enable performance metrics collection (speed insights)"},"replicas":{"type":"integer","format":"int32","description":"Number of replicas/instances to run\nDefaults to 1 replica"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig","description":"Security configuration (headers, rate limiting, attack mode, etc.)\nThese settings inherit and override from parent level (Environment > Project > Global)"}]},"sessionRecordingEnabled":{"type":"boolean","description":"Enable session recording for analytics"},"targetLabels":{"description":"Label selector for node-based scheduling. Replicas are only deployed to\nnodes whose labels match the selector.\n\nMatching rules:\n- **Same key, array value** → OR: node must match any value\n- **Different keys** → AND: node must satisfy all keys\n\nExample: `{\"region\": [\"us\", \"asia\"], \"gpu\": \"true\"}`\n→ (region=us OR region=asia) AND gpu=true\n\nApplied after `target_nodes` filtering (they stack)."},"targetNodes":{"type":["array","null"],"items":{"type":"integer","format":"int32"},"description":"Optional list of node IDs to deploy to. When set, replicas are distributed\nonly across these nodes (round-robin). When None, the scheduler distributes\nacross all active nodes (or deploys locally if no nodes exist)."},"wakeTimeoutSeconds":{"type":"integer","format":"int32","description":"Max seconds to wait for containers to start when waking from on-demand sleep.\nRequests return 503 if exceeded. Default: 30."}}},"DeploymentConfigSnapshot":{"type":"object","description":"Deployment configuration snapshot for deployments\n\nThis extends DeploymentConfig with environment variables to capture\nthe complete state of a deployment at the time it was created.","properties":{"automaticDeploy":{"type":"boolean","description":"Enable automatic deployments on git push"},"containerExecEnabled":{"type":"boolean","description":"Enable container exec/shell access"},"cpuLimit":{"type":["integer","null"],"format":"int32","description":"CPU limit in millicores"},"cpuRequest":{"type":["integer","null"],"format":"int32","description":"CPU request in millicores"},"environmentVariables":{"type":"object","description":"Environment variables used for this deployment","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container"},"memoryLimit":{"type":["integer","null"],"format":"int32","description":"Memory limit in megabytes"},"memoryRequest":{"type":["integer","null"],"format":"int32","description":"Memory request in megabytes"},"performanceMetricsEnabled":{"type":"boolean","description":"Enable performance metrics collection"},"replicas":{"type":"integer","format":"int32","description":"Number of replicas"},"sessionRecordingEnabled":{"type":"boolean","description":"Enable session recording"}}},"DeploymentConfiguration":{"type":"object","description":"Deployment-level configuration","required":["image","strategy","env_vars","ports","volumes","network","resources"],"properties":{"build":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/BuildConfiguration","description":"Build configuration (if building from source)"}]},"command":{"type":["array","null"],"items":{"type":"string"},"description":"Command override"},"entrypoint":{"type":["array","null"],"items":{"type":"string"},"description":"Entrypoint override"},"env_vars":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariable"},"description":"Environment variables"},"git":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GitSourcePlan","description":"Where the application's source code lives, when the source platform\nbuilds from a git repository. Execution uses this to link the temps\nproject to the same repository so the real deployment pipeline can\nclone and build it."}]},"health_check":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/HealthCheckConfiguration","description":"Health check configuration"}]},"image":{"type":"string","description":"Image to deploy"},"network":{"$ref":"#/components/schemas/NetworkConfiguration","description":"Network configuration"},"ports":{"type":"array","items":{"$ref":"#/components/schemas/PortMapping"},"description":"Port mappings"},"resources":{"$ref":"#/components/schemas/ResourceLimits","description":"Resource limits"},"strategy":{"$ref":"#/components/schemas/DeploymentStrategy","description":"Deployment strategy"},"volumes":{"type":"array","items":{"$ref":"#/components/schemas/VolumeMount"},"description":"Volume mounts"},"working_dir":{"type":["string","null"],"description":"Working directory"}}},"DeploymentContainerLogContentResponse":{"type":"object","description":"A single captured container-log dump, including its full text content.","required":["id","container_name","size_bytes","truncated","captured_at","content"],"properties":{"captured_at":{"type":"integer","format":"int64"},"container_name":{"type":"string"},"content":{"type":"string","description":"The captured plain-text log content."},"id":{"type":"integer","format":"int32"},"service_name":{"type":["string","null"]},"size_bytes":{"type":"integer","format":"int64"},"truncated":{"type":"boolean"}}},"DeploymentContainerLogResponse":{"type":"object","description":"Metadata for one captured (historical) container-log dump. Listed on the\ndeployment detail page so a user can pick which past container's logs to read.","required":["id","deployment_id","container_id","container_name","size_bytes","truncated","captured_at"],"properties":{"captured_at":{"type":"integer","format":"int64","description":"Unix epoch milliseconds of when the logs were captured (just before\nteardown). Matches the timestamp convention used by `DeploymentResponse`."},"container_id":{"type":"string"},"container_name":{"type":"string"},"deployment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"node_id":{"type":["integer","null"],"format":"int32"},"service_name":{"type":["string","null"]},"size_bytes":{"type":"integer","format":"int64"},"truncated":{"type":"boolean"}}},"DeploymentContainerLogsListResponse":{"type":"object","description":"The list of captured container-log dumps for a deployment.","required":["logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentContainerLogResponse"}}}},"DeploymentEnvironmentResponse":{"type":"object","required":["id","name","slug","domains"],"properties":{"domains":{"type":"array","items":{"type":"string"}},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"DeploymentJobResponse":{"type":"object","required":["id","deployment_id","job_id","job_type","name","status","created_at","updated_at","log_id"],"properties":{"created_at":{"type":"integer","format":"int64"},"dependencies":{},"deployment_id":{"type":"integer","format":"int32"},"description":{"type":["string","null"]},"error_message":{"type":["string","null"]},"execution_order":{"type":["integer","null"],"format":"int32"},"finished_at":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"job_config":{"description":"Internal workflow configuration is intentionally redacted. It can\ncontain legacy plaintext secrets or encrypted secret envelopes."},"job_id":{"type":"string"},"job_type":{"type":"string"},"log_id":{"type":"string"},"name":{"type":"string"},"outputs":{},"started_at":{"type":["integer","null"],"format":"int64"},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"DeploymentJobsResponse":{"type":"object","required":["jobs","total"],"properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentJobResponse"}},"total":{"type":"integer","minimum":0}}},"DeploymentListResponse":{"type":"object","required":["deployments","total","page","per_page"],"properties":{"deployments":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentResponse"}},"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"total":{"type":"integer","format":"int64"}}},"DeploymentMetadata":{"type":"object","description":"Deployment metadata - typed information about the deployment","properties":{"buildDurationMs":{"type":["integer","null"],"format":"int64","description":"Build duration in milliseconds"},"builder":{"type":["string","null"],"description":"Docker builder used (e.g., \"nixpacks\", \"dockerfile\")"},"deploymentDurationMs":{"type":["integer","null"],"format":"int64","description":"Deployment duration in milliseconds"},"deploymentSourceType":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SourceType","description":"Source type for THIS specific deployment (for Manual/flexible projects)\nThis allows Manual projects to have deployments via different methods\n(docker_image, static_files, or git) while keeping per-deployment tracking"}]},"dockerfilePath":{"type":["string","null"],"description":"Dockerfile path if using Dockerfile builder"},"externalImageId":{"type":["integer","null"],"format":"int32","description":"External image ID (reference to external_images table)"},"externalImageRef":{"type":["string","null"],"description":"External Docker image reference (for docker_image source type)\ne.g., \"ghcr.io/org/app:v1.0\" or \"docker.io/myapp:sha-abc123\""},"fileCount":{"type":["integer","null"],"format":"int32","description":"Number of files in the build output"},"gitPushEvent":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GitPushEvent","description":"Git push event that triggered this deployment (if from webhook)"}]},"healthCheckPath":{"type":["string","null"],"description":"Explicit deploy-time HTTP health-check path override.\nImage/static deploys can't read `.temps.yaml`, so this lets the deploy\nrequest set a custom path (e.g. \"/api/healthz\"). When present it takes\npriority over any `.temps.yaml` `health.path` value. Always starts with '/'."},"imageSizeBytes":{"type":["integer","null"],"format":"int64","description":"Total size of the built image in bytes"},"imageUploadedLocally":{"type":"boolean","description":"Whether the image was uploaded directly (via docker save/load) rather than pulled from registry\nWhen true, the PullExternalImageJob is skipped since the image is already loaded locally"},"isRollback":{"type":"boolean","description":"Whether this is a rollback deployment"},"labels":{"type":"array","items":{"type":"string"},"description":"Custom labels/tags for the deployment"},"rolledBackFromId":{"type":["integer","null"],"format":"int32","description":"ID of the deployment this was rolled back from (if applicable)"},"staticBundleContentType":{"type":["string","null"],"description":"Static bundle content type (for proper extraction: application/gzip or application/zip)"},"staticBundleId":{"type":["integer","null"],"format":"int32","description":"Static bundle ID (reference to static_bundles table, for static_files source type)"},"staticBundlePath":{"type":["string","null"],"description":"Static bundle path in blob storage (for static_files source type)"},"uploadedImageId":{"type":["string","null"],"description":"Docker image ID of the locally uploaded image (sha256:...)\nUsed to verify the image exists before deployment"}}},"DeploymentResponse":{"type":"object","required":["id","project_id","environment_id","environment","status","url","created_at","is_current"],"properties":{"branch":{"type":["string","null"]},"cancelled_reason":{"type":["string","null"]},"commit_author":{"type":["string","null"]},"commit_date":{"type":["integer","null"],"format":"int64"},"commit_hash":{"type":["string","null"]},"commit_message":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"deployment_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentConfigSnapshot","description":"Deployment configuration snapshot (CPU, memory, replicas, environment variables, etc.)"}]},"environment":{"$ref":"#/components/schemas/DeploymentEnvironmentResponse"},"environment_id":{"type":"integer","format":"int32"},"finished_at":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"is_current":{"type":"boolean"},"metadata":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentMetadata","description":"Deployment metadata (build info, git event, etc.)"}]},"project_id":{"type":"integer","format":"int32"},"screenshot_location":{"type":["string","null"]},"started_at":{"type":["integer","null"],"format":"int64"},"status":{"type":"string"},"tag":{"type":["string","null"]},"url":{"type":"string"}}},"DeploymentStateResponse":{"type":"object","required":["id","state","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"state":{"type":"string"}}},"DeploymentStrategy":{"type":"string","description":"Deployment strategy","enum":["replace","blue-green","rolling"]},"DeploymentTokenListResponse":{"type":"object","required":["tokens","total"],"properties":{"tokens":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentTokenResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"DeploymentTokenResponse":{"type":"object","required":["id","project_id","name","token_prefix","is_active","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"created_by":{"type":["integer","null"],"format":"int32"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"project_id":{"type":"integer","format":"int32"},"token_prefix":{"type":"string"}}},"DetectionConfig":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/StaticParams","description":"v0 (shipping): static threshold comparison of the aggregated value."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["static"]}}}],"description":"v0 (shipping): static threshold comparison of the aggregated value."},{"allOf":[{"$ref":"#/components/schemas/AnomalyParams","description":"Seasonal anomaly band (basic/agile/robust/ewma share this variant — the\nalgorithm is a field, not a new kind). Creation rejected until evaluated."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["anomaly"]}}}],"description":"Seasonal anomaly band (basic/agile/robust/ewma share this variant — the\nalgorithm is a field, not a new kind). Creation rejected until evaluated."},{"allOf":[{"$ref":"#/components/schemas/ForecastParams","description":"Predict a future threshold breach (capacity planning). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["forecast"]}}}],"description":"Predict a future threshold breach (capacity planning). Stub."},{"allOf":[{"$ref":"#/components/schemas/OutlierParams","description":"Cross-series population outlier (one host misbehaving vs its peers). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["outlier"]}}}],"description":"Cross-series population outlier (one host misbehaving vs its peers). Stub."},{"allOf":[{"$ref":"#/components/schemas/AutoWatchParams","description":"Watchdog-style self-tuning auto-watch (engine picks bounds). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["auto_watch"]}}}],"description":"Watchdog-style self-tuning auto-watch (engine picks bounds). Stub."}],"description":"The typed detector definition stored (as jsonb) in\n`metric_alert_rules.detection_config`.\n\nToday only [`DetectionConfig::Static`] is evaluable; the other variants are\nschema-present (so the SDK/UI and storage are already future-shaped) but\nrejected by [`DetectionConfig::validate`] until their evaluator lands. Each is\nthen enabled code-only, with no schema migration."},"DeviceCount":{"type":"object","required":["device_type","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"device_type":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"DigestSections":{"type":"object","description":"Sections that can be included in the weekly digest\nNote: `#[serde(default)]` allows backward compatibility when deserializing\nold data that may have `security` and `resources` fields instead of `projects`","properties":{"deployments":{"type":"boolean","default":true},"errors":{"type":"boolean","default":true},"funnels":{"type":"boolean","default":true},"performance":{"type":"boolean","default":true},"projects":{"type":"boolean","default":true}}},"Direction":{"type":"string","description":"Which side(s) of an anomaly band count as a deviation.","enum":["both","above","below"]},"DisableBlobResponse":{"type":"object","description":"Response after disabling Blob service","required":["success","message"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service disabled successfully"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"DisableKvResponse":{"type":"object","description":"Response after disabling KV service","required":["success","message"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service disabled successfully"},"success":{"type":"boolean","description":"Whether the service was successfully disabled"}}},"DisableMfaRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"DiscoverRequest":{"type":"object","description":"Request to discover workloads","required":["source"],"properties":{"credentials":{"$ref":"#/components/schemas/ImportCredentials","description":"Platform credentials (required for cloud platforms like Vercel, Railway)"},"selector":{"$ref":"#/components/schemas/ImportSelector","description":"Optional selector to filter workloads"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source to discover from"}}},"DiscoverResponse":{"type":"object","description":"Response with discovered workloads","required":["workloads"],"properties":{"workloads":{"type":"array","items":{"$ref":"#/components/schemas/WorkloadDescriptor"},"description":"Discovered workloads"}}},"DiskInfo":{"type":"object","description":"Disk space information for a single disk/partition","required":["mount_point","total_bytes","used_bytes","available_bytes","usage_percent","file_system"],"properties":{"available_bytes":{"type":"integer","format":"int64","description":"Available space in bytes","minimum":0},"file_system":{"type":"string","description":"File system type (e.g., \"ext4\", \"apfs\")"},"mount_point":{"type":"string","description":"Mount point of the disk"},"total_bytes":{"type":"integer","format":"int64","description":"Total space in bytes","minimum":0},"usage_percent":{"type":"number","format":"double","description":"Usage percentage (0-100)"},"used_bytes":{"type":"integer","format":"int64","description":"Used space in bytes","minimum":0}}},"DiskSpaceAlert":{"type":"object","description":"Alert for a disk that exceeds the threshold","required":["mount_point","usage_percent","threshold_percent","available_bytes","available_human"],"properties":{"available_bytes":{"type":"integer","format":"int64","description":"Available space in bytes","minimum":0},"available_human":{"type":"string","description":"Human-readable available space"},"mount_point":{"type":"string","description":"Mount point of the disk"},"threshold_percent":{"type":"integer","format":"int32","description":"Configured threshold percentage","minimum":0},"usage_percent":{"type":"number","format":"double","description":"Current usage percentage"}}},"DiskSpaceAlertSettings":{"type":"object","description":"Disk space alert settings for monitoring disk usage","properties":{"check_interval_seconds":{"type":"integer","format":"int64","description":"Interval in seconds between disk space checks","default":300,"example":300,"minimum":60},"enabled":{"type":"boolean","description":"Whether disk space alerts are enabled","default":true},"monitor_path":{"type":["string","null"],"description":"Restrict monitoring to the disk backing this path. When unset (the\ndefault), every mounted writable volume is monitored — including\ndedicated volumes such as `/var/lib/docker`.","default":null},"threshold_percent":{"type":"integer","format":"int32","description":"Threshold percentage (0-100) at which to trigger alerts","default":80,"example":80,"maximum":100,"minimum":0}}},"DiskSpaceCheckResult":{"type":"object","description":"Result of a disk space check","required":["checked_at","enabled","threshold_percent","disks","alerts"],"properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/DiskSpaceAlert"},"description":"Disks that meet or exceed the threshold"},"checked_at":{"type":"string","format":"date-time","description":"Timestamp of the check (ISO 8601, UTC)","example":"2026-05-28T12:15:47.609192Z"},"disks":{"type":"array","items":{"$ref":"#/components/schemas/DiskInfo"},"description":"List of all monitored disks"},"enabled":{"type":"boolean","description":"Whether disk space monitoring is enabled in settings"},"threshold_percent":{"type":"integer","format":"int32","description":"Configured alert threshold percentage (0-100)","minimum":0}}},"DnsAckRequest":{"type":"object","required":["applied_generation"],"properties":{"applied_generation":{"type":"integer","format":"int64","description":"Highest generation the agent has actually applied locally."}}},"DnsAckResponse":{"type":"object","required":["node_id","applied_generation","server_generation"],"properties":{"applied_generation":{"type":"integer","format":"int64"},"node_id":{"type":"integer","format":"int32"},"server_generation":{"type":"integer","format":"int64"}}},"DnsChallengeRecordResult":{"type":"object","description":"Result of a single DNS TXT record creation for ACME challenge","required":["name","value","success","message"],"properties":{"message":{"type":"string","description":"Human-readable message about the operation"},"name":{"type":"string","description":"TXT record name (e.g., \"_acme-challenge.example.com\")","example":"_acme-challenge.example.com"},"success":{"type":"boolean","description":"Whether the record was created successfully"},"value":{"type":"string","description":"TXT record value (the ACME challenge token)","example":"abc123..."}}},"DnsChangesResponse":{"type":"object","required":["generation","full_snapshot","records","removed_ids"],"properties":{"full_snapshot":{"type":"boolean","description":"`true` ⇒ replace the local zone with `records`. `false` ⇒ merge\n`records` into the existing zone (and remove `removed_ids`)."},"generation":{"type":"integer","format":"int64","description":"Highest generation included in this response. Agent ACKs this back."},"records":{"type":"array","items":{"$ref":"#/components/schemas/EndpointDto"}},"removed_ids":{"type":"array","items":{"type":"integer","format":"int64"},"description":"IDs the agent should remove from its zone. Always empty in the v1\nprotocol — the resolver reconciles by name on snapshot mode. Kept\nin the wire format so a future tombstone-based protocol doesn't\nrequire a breaking change."}}},"DnsCompletionResponse":{"type":"object","required":["domain","status"],"properties":{"domain":{"type":"string"},"status":{"type":"string"}}},"DnsLookupError":{"type":"object","description":"Error response for DNS lookup failures","required":["error","domain"],"properties":{"domain":{"type":"string","description":"Domain name that failed","example":"nonexistent.com"},"error":{"type":"string","description":"Error message","example":"DNS lookup failed: domain not found"}}},"DnsLookupRequest":{"type":"object","description":"Request to lookup DNS A records for a domain","required":["domain"],"properties":{"domain":{"type":"string","description":"Domain name to lookup","example":"example.com"}}},"DnsLookupResponse":{"type":"object","description":"Response containing DNS A records","required":["domain","records","count","dns_servers"],"properties":{"count":{"type":"integer","description":"Number of records found","example":1,"minimum":0},"dns_servers":{"type":"array","items":{"type":"string"},"description":"DNS servers used for the lookup","example":["8.8.8.8","8.8.4.4"]},"domain":{"type":"string","description":"Domain name that was queried","example":"example.com"},"records":{"type":"array","items":{"type":"string"},"description":"List of A record IP addresses","example":["93.184.216.34"]}}},"DnsProviderCredentials":{"oneOf":[{"type":"object","required":["api_token","type"],"properties":{"account_id":{"type":["string","null"]},"api_token":{"type":"string","example":"your-api-token"},"type":{"type":"string","enum":["cloudflare"]}}},{"type":"object","required":["api_user","api_key","type"],"properties":{"api_key":{"type":"string","example":"your-api-key"},"api_user":{"type":"string","example":"your-username"},"client_ip":{"type":["string","null"]},"sandbox":{"type":"boolean"},"type":{"type":"string","enum":["namecheap"]}}},{"type":"object","required":["access_key_id","secret_access_key","type"],"properties":{"access_key_id":{"type":"string","example":"AKIAIOSFODNN7EXAMPLE"},"region":{"type":["string","null"],"example":"us-east-1"},"secret_access_key":{"type":"string","example":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"},"session_token":{"type":["string","null"]},"type":{"type":"string","enum":["route53"]}}},{"type":"object","required":["api_token","type"],"properties":{"api_token":{"type":"string","example":"dop_v1_your-token"},"type":{"type":"string","enum":["digitalocean"]}}},{"type":"object","required":["service_account_email","private_key","project_id","type"],"properties":{"private_key":{"type":"string","example":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"},"project_id":{"type":"string","example":"my-gcp-project"},"service_account_email":{"type":"string","example":"dns-admin@myproject.iam.gserviceaccount.com"},"type":{"type":"string","enum":["gcp"]}}},{"type":"object","required":["tenant_id","client_id","client_secret","subscription_id","resource_group","type"],"properties":{"client_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"client_secret":{"type":"string"},"resource_group":{"type":"string","example":"my-resource-group"},"subscription_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"tenant_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"type":{"type":"string","enum":["azure"]}}},{"type":"object","description":"Pebble challtestsrv mock DNS (LOCAL DEV/TEST ONLY)","required":["management_url","type"],"properties":{"management_url":{"type":"string","example":"http://localhost:8055"},"type":{"type":"string","enum":["pebble"]}}}],"description":"DNS provider credentials (API-facing)"},"DnsProviderResponse":{"type":"object","description":"DNS provider response","required":["id","name","provider_type","credentials","is_active","flat_hostnames_supported","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"credentials":{"description":"Masked credentials for display"},"description":{"type":["string","null"]},"flat_hostnames_supported":{"type":"boolean","description":"Whether this provider benefits from the flat hostname mode (e.g. Cloudflare\nUniversal SSL). The UI surfaces/recommends the Flat toggle when true."},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_error":{"type":["string","null"]},"last_used_at":{"type":["string","null"]},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"string"}}},"DnsProviderSettings":{"type":"object","properties":{"cloudflare_api_key":{"type":["string","null"],"default":null},"provider":{"type":"string","default":"manual"}}},"DnsProviderSettingsMasked":{"type":"object","description":"DNS provider settings with masked sensitive fields","required":["provider"],"properties":{"cloudflare_api_key":{"type":["string","null"]},"provider":{"type":"string"}}},"DnsProviderType":{"type":"string","description":"Supported DNS provider types","enum":["cloudflare","namecheap","route53","digitalocean","gcp","azure","manual","pebble"]},"DnsRecord":{"type":"object","description":"A DNS record","required":["zone","name","fqdn","content","ttl"],"properties":{"content":{"$ref":"#/components/schemas/DnsRecordContent","description":"Record content"},"fqdn":{"type":"string","description":"Fully qualified domain name","example":"www.example.com"},"id":{"type":["string","null"],"description":"Provider-specific record ID (if exists)","example":"abc123"},"metadata":{"type":"object","description":"Provider-specific metadata","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Record name (without zone, e.g., \"www\" or \"@\" for root)","example":"www"},"proxied":{"type":"boolean","description":"Whether this record is proxied (Cloudflare-specific)"},"ttl":{"type":"integer","format":"int32","description":"Time to live in seconds","example":300,"minimum":0},"zone":{"type":"string","description":"Zone/domain this record belongs to","example":"example.com"}}},"DnsRecordChange":{"type":"object","description":"A single DNS record change the Cloudflare sync would make.","required":["action","name","record_type","value"],"properties":{"action":{"type":"string","description":"`\"create\"`, `\"update\"`, or `\"delete\"`."},"name":{"type":"string"},"record_type":{"type":"string","description":"Record type, e.g. `\"A\"` or `\"CNAME\"`."},"value":{"type":"string"}}},"DnsRecordContent":{"oneOf":[{"type":"object","description":"A record - IPv4 address (as string, e.g., \"192.0.2.1\")","required":["value","type"],"properties":{"type":{"type":"string","enum":["A"]},"value":{"type":"object","description":"A record - IPv4 address (as string, e.g., \"192.0.2.1\")","required":["address"],"properties":{"address":{"type":"string","example":"192.0.2.1"}}}}},{"type":"object","description":"AAAA record - IPv6 address (as string, e.g., \"2001:db8::1\")","required":["value","type"],"properties":{"type":{"type":"string","enum":["AAAA"]},"value":{"type":"object","description":"AAAA record - IPv6 address (as string, e.g., \"2001:db8::1\")","required":["address"],"properties":{"address":{"type":"string","example":"2001:db8::1"}}}}},{"type":"object","description":"CNAME record - canonical name","required":["value","type"],"properties":{"type":{"type":"string","enum":["CNAME"]},"value":{"type":"object","description":"CNAME record - canonical name","required":["target"],"properties":{"target":{"type":"string"}}}}},{"type":"object","description":"TXT record - text content","required":["value","type"],"properties":{"type":{"type":"string","enum":["TXT"]},"value":{"type":"object","description":"TXT record - text content","required":["content"],"properties":{"content":{"type":"string"}}}}},{"type":"object","description":"MX record - mail exchange","required":["value","type"],"properties":{"type":{"type":"string","enum":["MX"]},"value":{"type":"object","description":"MX record - mail exchange","required":["priority","target"],"properties":{"priority":{"type":"integer","format":"int32","minimum":0},"target":{"type":"string"}}}}},{"type":"object","description":"NS record - nameserver","required":["value","type"],"properties":{"type":{"type":"string","enum":["NS"]},"value":{"type":"object","description":"NS record - nameserver","required":["nameserver"],"properties":{"nameserver":{"type":"string"}}}}},{"type":"object","description":"SRV record - service","required":["value","type"],"properties":{"type":{"type":"string","enum":["SRV"]},"value":{"type":"object","description":"SRV record - service","required":["priority","weight","port","target"],"properties":{"port":{"type":"integer","format":"int32","minimum":0},"priority":{"type":"integer","format":"int32","minimum":0},"target":{"type":"string"},"weight":{"type":"integer","format":"int32","minimum":0}}}}},{"type":"object","description":"CAA record - certification authority authorization","required":["value","type"],"properties":{"type":{"type":"string","enum":["CAA"]},"value":{"type":"object","description":"CAA record - certification authority authorization","required":["flags","tag","value"],"properties":{"flags":{"type":"integer","format":"int32","minimum":0},"tag":{"type":"string"},"value":{"type":"string"}}}}},{"type":"object","description":"PTR record - pointer","required":["value","type"],"properties":{"type":{"type":"string","enum":["PTR"]},"value":{"type":"object","description":"PTR record - pointer","required":["target"],"properties":{"target":{"type":"string"}}}}}],"description":"DNS record content - varies by record type"},"DnsRecordResponse":{"type":"object","required":["record_type","name","value","status"],"properties":{"name":{"type":"string","description":"DNS record name (host)","example":"temps._domainkey.example.com"},"priority":{"type":["integer","null"],"format":"int32","description":"Priority (for MX records)","example":"10","minimum":0},"record_type":{"type":"string","description":"Record type: TXT, CNAME, MX","example":"TXT"},"status":{"$ref":"#/components/schemas/DnsRecordStatusResponse","description":"Verification status: unknown, verified, pending, failed"},"value":{"type":"string","description":"DNS record value","example":"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3..."}}},"DnsRecordSetupResult":{"type":"object","description":"Result of a single DNS record creation","required":["record_type","name","success","automatic","message"],"properties":{"automatic":{"type":"boolean","description":"Whether the operation was automatic or manual"},"message":{"type":"string","description":"Human-readable message"},"name":{"type":"string","description":"Record name"},"record_type":{"type":"string","description":"Record type (TXT, CNAME, MX)"},"success":{"type":"boolean","description":"Whether the record was created successfully"}}},"DnsRecordStatusResponse":{"type":"string","description":"DNS record verification status","enum":["unknown","verified","pending","failed"]},"DnsZone":{"type":"object","description":"A DNS zone (domain managed by the provider)","required":["id","name","status","nameservers"],"properties":{"id":{"type":"string","description":"Provider-specific zone ID","example":"zone123"},"metadata":{"type":"object","description":"Provider-specific metadata","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Zone name (domain)","example":"example.com"},"nameservers":{"type":"array","items":{"type":"string"},"description":"Nameservers for this zone"},"status":{"type":"string","description":"Zone status","example":"active"}}},"DockerComposePresetConfig":{"type":"object","description":"Configuration for Docker Compose deployments.","properties":{"composeOverride":{"type":["string","null"],"description":"User-provided docker-compose.override.yml content."},"composePath":{"type":["string","null"],"description":"Path to the Compose file relative to the project directory."},"publicPorts":{"type":"array","items":{"$ref":"#/components/schemas/ComposePublicPort"},"description":"Compose service ports that should be publicly routed."}}},"DockerRegistrySettings":{"type":"object","properties":{"ca_certificate":{"type":["string","null"],"default":null},"enabled":{"type":"boolean","default":false},"password":{"type":["string","null"],"default":null},"registry_url":{"type":["string","null"],"default":null},"tls_verify":{"type":"boolean","default":true},"username":{"type":["string","null"],"default":null}}},"DockerRegistrySettingsMasked":{"type":"object","description":"Docker registry settings with masked sensitive fields","required":["enabled","tls_verify"],"properties":{"ca_certificate":{"type":["string","null"]},"enabled":{"type":"boolean"},"password":{"type":["string","null"]},"registry_url":{"type":["string","null"]},"tls_verify":{"type":"boolean"},"username":{"type":["string","null"]}}},"DockerfilePresetConfig":{"type":"object","description":"Configuration for Dockerfile preset\nAllows customizing the Dockerfile path and build context for Docker-based deployments","properties":{"buildContext":{"type":["string","null"],"description":"Custom build context path (relative to repository root)\nIf not specified, uses the project's directory setting","example":"./api"},"dockerfilePath":{"type":["string","null"],"description":"Custom Dockerfile path (relative to build context)\nIf not specified, defaults to \"Dockerfile\" in the build context","example":"docker/Dockerfile"},"variant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DockerfileVariant","description":"Catalog variant. Normally omitted; `custom` selects the generated\nDockerfile compatibility preset."}]}}},"DockerfileVariant":{"type":"string","description":"Catalog variant persisted under the canonical Dockerfile preset.\n\nExisting rows predate this discriminator and therefore deserialize as\n[`DockerfileVariant::File`].","enum":["file","custom"]},"DomainAction":{"type":"string","description":"What to do with a domain during migration","enum":["import","skip"]},"DomainChallengeResponse":{"type":"object","required":["domain","txt_records","status"],"properties":{"domain":{"type":"string"},"status":{"type":"string"},"txt_records":{"type":"array","items":{"$ref":"#/components/schemas/TxtRecord"},"description":"Array of TXT records to add to DNS. For wildcards, multiple records are required."}}},"DomainEnvironmentResponse":{"type":"object","required":["id","name","slug"],"properties":{"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"DomainError":{"type":"object","required":["message","code"],"properties":{"code":{"type":"string"},"details":{"type":["string","null"]},"message":{"type":"string"}}},"DomainPlan":{"type":"object","description":"Plan for migrating a single custom domain","required":["domain","environment","action","action_description"],"properties":{"action":{"$ref":"#/components/schemas/DomainAction","description":"What to do with this domain"},"action_description":{"type":"string","description":"Human-readable explanation"},"domain":{"type":"string","description":"Full domain name"},"environment":{"type":"string","description":"Which environment to associate with (\"production\")"},"redirect_to":{"type":["string","null"],"description":"Redirect target (if this is a redirect domain)"},"replacement":{"type":["string","null"],"description":"The temps-side address that replaces this domain when it is skipped.\n\nSource-generated domains (sslip.io / traefik.me / platform subdomains)\nembed the source server's IP and would keep pointing at the old\nmachine — this tells the user where the app will be reachable on\ntemps instead."},"status_code":{"type":["integer","null"],"format":"int32","description":"Redirect status code"}}},"DomainResponse":{"type":"object","required":["id","domain","status","is_wildcard","verification_method","created_at","updated_at"],"properties":{"certificate":{"type":["string","null"],"description":"The PEM-encoded certificate chain (can be displayed in browser or downloaded)"},"created_at":{"type":"integer","format":"int64"},"dns_challenge_token":{"type":["string","null"]},"dns_challenge_value":{"type":["string","null"]},"domain":{"type":"string"},"expiration_time":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"is_wildcard":{"type":"boolean"},"last_error":{"type":["string","null"]},"last_error_type":{"type":["string","null"]},"last_renewed":{"type":["integer","null"],"format":"int64"},"on_demand_backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand TLS negative-cache deadline (epoch millis), when this hostname's\non-demand HTTP-01 issuance is in backoff after a failure (ADR-018 §4).\n`None` means no active backoff."},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"},"verification_method":{"type":"string"}}},"DrainNodeResponse":{"type":"object","required":["id","name","status","affected_environments","message"],"properties":{"affected_environments":{"type":"integer","minimum":0},"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"DrainStatusResponse":{"type":"object","description":"Progress of a node drain operation.","required":["node_id","node_name","status","remaining_containers","drain_complete","can_remove","message"],"properties":{"can_remove":{"type":"boolean","description":"Can the node be safely removed?"},"drain_complete":{"type":"boolean","description":"Whether the drain is complete (all containers migrated)"},"message":{"type":"string"},"node_id":{"type":"integer","format":"int32"},"node_name":{"type":"string"},"remaining_containers":{"type":"integer","description":"Number of containers still on this node","minimum":0},"status":{"type":"string"}}},"DropOffPoint":{"type":"object","description":"Drop-off point: pages where visitors leave the site","required":["page_path","exit_count","total_views","exit_rate"],"properties":{"exit_count":{"type":"integer","format":"int64","description":"Number of exits from this page"},"exit_rate":{"type":"number","format":"double","description":"Exit rate for this page (exit_count / total_views)"},"page_path":{"type":"string","description":"The page path where visitors drop off"},"total_views":{"type":"integer","format":"int64","description":"Total views of this page"}}},"EmailConfig":{"type":"object","required":["smtp_host","smtp_port","username","password","from_address","to_addresses"],"properties":{"accept_invalid_certs":{"type":"boolean"},"from_address":{"type":"string"},"from_name":{"type":["string","null"]},"password":{"type":"string"},"smtp_host":{"type":"string"},"smtp_port":{"type":"integer","format":"int32","minimum":0},"starttls_required":{"type":"boolean"},"tls_mode":{"$ref":"#/components/schemas/TlsMode"},"to_addresses":{"type":"array","items":{"type":"string"}},"username":{"type":"string"}}},"EmailDomainResponse":{"type":"object","required":["id","provider_id","domain","status","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"domain":{"type":"string","example":"updates.example.com"},"id":{"type":"integer","format":"int32"},"last_verified_at":{"type":["string","null"]},"provider_id":{"type":"integer","format":"int32"},"status":{"type":"string","example":"verified"},"updated_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"verification_error":{"type":["string","null"]}}},"EmailDomainWithDnsResponse":{"type":"object","required":["domain","dns_records"],"properties":{"dns_records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordResponse"}},"domain":{"$ref":"#/components/schemas/EmailDomainResponse"}}},"EmailProviderResponse":{"type":"object","required":["id","name","provider_type","region","is_active","credentials","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"credentials":{"description":"Masked credentials for display"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string","example":"My AWS SES"},"provider_type":{"$ref":"#/components/schemas/EmailProviderTypeRoute"},"region":{"type":"string","example":"us-east-1"},"sns_topic_arn":{"type":["string","null"]},"updated_at":{"type":"string","example":"2025-12-03T10:30:00Z"}}},"EmailProviderTypeRoute":{"type":"string","enum":["ses","scaleway","smtp"]},"EmailRequest":{"type":"object","description":"Request body carrying just an email address (password-reset request).","required":["email"],"properties":{"email":{"type":"string"}}},"EmailResponse":{"type":"object","required":["id","from_address","to_addresses","subject","status","created_at","track_opens","track_clicks","open_count","click_count"],"properties":{"bcc_addresses":{"type":["array","null"],"items":{"type":"string"}},"cc_addresses":{"type":["array","null"],"items":{"type":"string"}},"click_count":{"type":"integer","format":"int32","description":"Number of times links in the email were clicked"},"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"domain_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"first_clicked_at":{"type":["string","null"],"description":"When a link was first clicked"},"first_opened_at":{"type":["string","null"],"description":"When the email was first opened"},"from_address":{"type":"string","example":"hello@updates.example.com"},"from_name":{"type":["string","null"]},"headers":{"type":["object","null"],"additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"html_body":{"type":["string","null"]},"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"open_count":{"type":"integer","format":"int32","description":"Number of times the email was opened"},"project_id":{"type":["integer","null"],"format":"int32"},"provider_message_id":{"type":["string","null"]},"reply_to":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"status":{"type":"string","example":"sent"},"subject":{"type":"string"},"tags":{"type":["array","null"],"items":{"type":"string"}},"text_body":{"type":["string","null"]},"to_addresses":{"type":"array","items":{"type":"string"}},"track_clicks":{"type":"boolean","description":"Whether click tracking is enabled"},"track_opens":{"type":"boolean","description":"Whether open tracking is enabled"},"tracked_html_body":{"type":["string","null"],"description":"The final HTML sent to the provider (with tracking pixel and rewritten links)"}}},"EmailStatsResponse":{"type":"object","required":["total","sent","failed","queued","captured"],"properties":{"captured":{"type":"integer","format":"int64","description":"Emails captured without sending (Mailhog mode - no provider configured)","minimum":0},"failed":{"type":"integer","format":"int64","minimum":0},"queued":{"type":"integer","format":"int64","minimum":0},"sent":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"EmailStatusResponse":{"type":"object","required":["email_configured","password_reset_available","oidc_providers"],"properties":{"email_configured":{"type":"boolean"},"oidc_providers":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderSummary"}},"password_reset_available":{"type":"boolean"}}},"EmailTrackingResponse":{"type":"object","description":"Email tracking summary","required":["email_id","track_opens","track_clicks","open_count","click_count","unique_opens","unique_clicks","links"],"properties":{"click_count":{"type":"integer","format":"int32"},"email_id":{"type":"string"},"first_clicked_at":{"type":["string","null"]},"first_opened_at":{"type":["string","null"]},"links":{"type":"array","items":{"$ref":"#/components/schemas/TrackedLinkResponse"}},"open_count":{"type":"integer","format":"int32"},"track_clicks":{"type":"boolean"},"track_opens":{"type":"boolean"},"unique_clicks":{"type":"integer","format":"int64","minimum":0},"unique_opens":{"type":"integer","format":"int64","minimum":0}}},"EmailTrackingSetupResponse":{"type":"object","description":"Result of the one-click AWS-side event-tracking setup.","required":["topic_arn","webhook_url","subscription_requested","event_destination_attached"],"properties":{"event_destination_attached":{"type":"boolean","description":"The SESv2 event destination (bounce/complaint/delivery) is attached\nto the `temps-tracking` configuration set."},"subscription_requested":{"type":"boolean","description":"The webhook subscription was requested; SNS confirms it\nasynchronously through the webhook itself."},"topic_arn":{"type":"string","example":"arn:aws:sns:us-east-1:123456789012:temps-email-events-1"},"webhook_url":{"type":"string"}}},"EmailTrackingStatusResponse":{"type":"object","description":"Live status of the SES event-tracking pipeline for one provider.","required":["webhook_url","supports_event_tracking"],"properties":{"last_event_at":{"type":["string","null"],"description":"Most recent delivered/bounced/complained event recorded for an email\nsent through this provider. `null` means no provider feedback has\narrived yet.","example":"2026-07-18T10:31:00Z"},"sns_topic_arn":{"type":["string","null"]},"subscription_confirmed_at":{"type":["string","null"],"description":"When the SNS subscription for the current topic was confirmed.\n`null` with a topic set usually means the subscription is still\npending — most often because the endpoint was subscribed before the\ntopic ARN was saved here.","example":"2026-07-18T10:30:00Z"},"supports_event_tracking":{"type":"boolean","description":"Only SES providers support SNS event tracking."},"webhook_url":{"type":"string","description":"Public webhook endpoint SNS must deliver events to.","example":"https://temps.example.com/api/t/webhook/ses"}}},"EmbeddingData":{"type":"object","required":["object","embedding","index"],"properties":{"embedding":{"type":"array","items":{"type":"number","format":"double"}},"index":{"type":"integer","format":"int32"},"object":{"type":"string"}}},"EmbeddingInput":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"EmbeddingRequest":{"type":"object","required":["model","input"],"properties":{"dimensions":{"type":["integer","null"],"format":"int32"},"encoding_format":{"type":["string","null"]},"input":{"$ref":"#/components/schemas/EmbeddingInput"},"model":{"type":"string"}}},"EmbeddingResponse":{"type":"object","required":["object","data","model","usage"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmbeddingData"}},"model":{"type":"string"},"object":{"type":"string"},"usage":{"$ref":"#/components/schemas/EmbeddingUsage"}}},"EmbeddingUsage":{"type":"object","required":["prompt_tokens","total_tokens"],"properties":{"prompt_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"EnableBlobRequest":{"type":"object","description":"Request to enable Blob service","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (optional, defaults to RustFS)","example":"ghcr.io/rustfs/rustfs:0.5.0"},"root_password":{"type":["string","null"],"description":"Root password for S3 access"},"root_user":{"type":["string","null"],"description":"Root user for S3 access"}}},"EnableBlobResponse":{"type":"object","description":"Response after enabling Blob service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service enabled successfully"},"status":{"$ref":"#/components/schemas/BlobStatusResponse","description":"Current status"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"EnableKvRequest":{"type":"object","description":"Request to enable the KV service","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (optional, uses default if not provided)","example":"gotempsh/redis-walg:8-bookworm"},"max_memory":{"type":["string","null"],"description":"Maximum memory allocation (e.g., \"256mb\", \"1gb\")","example":"256mb"},"persistence":{"type":"boolean","description":"Enable data persistence"}}},"EnableKvResponse":{"type":"object","description":"Response after enabling KV service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service enabled successfully"},"status":{"$ref":"#/components/schemas/KvStatusResponse","description":"Current service status"},"success":{"type":"boolean","description":"Whether the service was successfully enabled"}}},"EnablePgStatStatementsResponse":{"type":"object","description":"Response for the enable pg_stat_statements endpoint.","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable message confirming the action."}}},"EndpointDto":{"type":"object","description":"One DNS record on the wire. Mirrors `service_endpoints::Model` but\nkeeps the API stable across entity evolution. `target_ip` is a string\n(v4 or v6 literal, or CNAME target hostname) parsed by the resolver.","required":["id","fqdn","record_type","ttl","owner_kind","owner_id","generation"],"properties":{"fqdn":{"type":"string"},"generation":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int64"},"node_id":{"type":["integer","null"],"format":"int32"},"owner_id":{"type":"integer","format":"int64"},"owner_kind":{"type":"string"},"record_type":{"type":"string"},"target_ip":{"type":["string","null"]},"target_port":{"type":["integer","null"],"format":"int32"},"ttl":{"type":"integer","format":"int32"}}},"EnqueuedJob":{"type":"object","description":"A single job that was successfully enqueued during a fan-out run.","required":["backup_id","job_id","engine"],"properties":{"backup_id":{"type":"integer","format":"int32","description":"FK to `backups.id` for this job."},"engine":{"type":"string","description":"Engine key (e.g. `\"control_plane\"`, `\"redis\"`, `\"postgres_pgdump\"`)."},"job_id":{"type":"integer","format":"int64","description":"FK to `backup_jobs.id` for this job."},"target_service_id":{"type":["integer","null"],"format":"int32","description":"FK to `external_services.id` when this is an external-service job.\n`None` for the control-plane job."}}},"EnrichVisitorRequest":{"type":"object","required":["custom_data"],"properties":{"custom_data":{"type":"object"}}},"EnrichVisitorResponse":{"type":"object","required":["success","visitor_id","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"},"visitor_id":{"type":"string"}}},"EnrollmentTokenInfo":{"type":"object","required":["id","expires_at","used_count","max_uses","created_at"],"properties":{"bound_node_name":{"type":["string","null"]},"created_at":{"type":"string"},"expires_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"max_uses":{"type":"integer","format":"int32"},"used_count":{"type":"integer","format":"int32"}}},"EnrollmentTokenListResponse":{"type":"object","required":["tokens"],"properties":{"tokens":{"type":"array","items":{"$ref":"#/components/schemas/EnrollmentTokenInfo"}}}},"EntityInfoResponse":{"type":"object","required":["container_path","entity","entity_type","fields"],"properties":{"container_path":{"type":"array","items":{"type":"string"},"description":"Full container path","example":["mydb","public"]},"entity":{"type":"string","description":"Entity name","example":"users"},"entity_type":{"type":"string","description":"Entity type","example":"table"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/FieldResponse"},"description":"Field definitions"},"metadata":{"description":"Additional metadata (content_type, last_modified, etag, etc.)"},"row_count":{"type":["integer","null"],"description":"Approximate row count (for tables/collections)","example":1234,"minimum":0},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes (for objects/files)","example":1048576,"minimum":0},"sort_schema":{"description":"JSON Schema for sort options (if supported)"}}},"EntityResponse":{"type":"object","required":["name","entity_type"],"properties":{"entity_type":{"type":"string","description":"Entity type (table, view, collection, etc.)","example":"table"},"name":{"type":"string","description":"Entity name (table/collection)","example":"users"},"row_count":{"type":["integer","null"],"description":"Approximate row count","example":1234,"minimum":0},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes (for files/objects)","example":1048576,"minimum":0}}},"EnvVarInput":{"type":"object","description":"Input for environment variable","required":["name","value"],"properties":{"name":{"type":"string","description":"Variable name"},"value":{"type":"string","description":"Variable value"}}},"EnvVarIntegrationInfo":{"type":"object","required":["service_id","service_name","service_type","service_updated_at"],"properties":{"service_id":{"type":"integer","format":"int32"},"service_name":{"type":"string"},"service_slug":{"type":["string","null"]},"service_type":{"type":"string"},"service_updated_at":{"type":"string"}}},"EnvVarResponse":{"type":"object","description":"Environment variable with masked sensitive values","required":["key","value","is_masked"],"properties":{"is_masked":{"type":"boolean","description":"Whether this is a sensitive/masked value"},"key":{"type":"string"},"value":{"type":"string"}}},"EnvVarTemplateResponse":{"type":"object","description":"Environment variable template response","required":["name","required"],"properties":{"default":{"type":["string","null"],"description":"Default value if not provided by user"},"default_generator":{"type":["string","null"],"description":"Frontend-side generator hint for the default value\n(e.g. `app_url`, `random_secret`, `random_hex_32`)"},"description":{"type":["string","null"],"description":"Description of what this variable is used for"},"example":{"type":["string","null"],"description":"Example value for documentation"},"name":{"type":"string","description":"Name of the environment variable"},"required":{"type":"boolean","description":"Whether this variable is required"}}},"EnvironmentConfiguration":{"type":"object","description":"Environment-level configuration","required":["name","subdomain","resources"],"properties":{"name":{"type":"string","description":"Environment name"},"resources":{"$ref":"#/components/schemas/ResourceLimits","description":"Resource limits for environment"},"subdomain":{"type":"string","description":"Proposed subdomain"}}},"EnvironmentDomainResponse":{"type":"object","required":["id","environment_id","domain","created_at","url"],"properties":{"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"url":{"type":"string","description":"Full URL for this domain (e.g., https://buildtolearndev-production.example.com)","example":"https://buildtolearndev-production.example.com"}}},"EnvironmentInfo":{"type":"object","required":["id","name","main_url"],"properties":{"current_deployment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"main_url":{"type":"string"},"name":{"type":"string"}}},"EnvironmentResponse":{"type":"object","required":["id","project_id","name","slug","main_url","subdomain","created_at","updated_at","is_preview","protected","sleeping"],"properties":{"attack_mode":{"type":["boolean","null"],"description":"Per-environment CAPTCHA attack-mode override.\n`null` means inherit the project-level `attack_mode`; `true`/`false`\nexplicitly enable/disable the challenge for this environment. Always\nserialized (NOT skipped) so the UI can distinguish `null` from `false`."},"branch":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"current_deployment_id":{"type":["integer","null"],"format":"int32"},"deployment_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentConfig","description":"Deployment configuration for this environment (overrides project-level config)"}]},"estimated_sleep_at":{"type":["integer","null"],"format":"int64","description":"Estimated time (epoch millis) when the environment will go to sleep\nbased on last activity + idle timeout. NULL when sleeping or on-demand disabled."},"force_https":{"type":["boolean","null"],"description":"Per-environment HTTP→HTTPS redirect override.\n`null` means inherit the proxy default (redirect only when the host has\nan active TLS certificate); `true` always redirects plain HTTP for this\nenvironment, `false` never does. Always serialized (NOT skipped) so the\nUI can distinguish `null` from `false`."},"id":{"type":"integer","format":"int32"},"is_preview":{"type":"boolean","description":"Indicates if this is a preview environment (auto-created per branch)\nFor preview environments, 'branch' contains the feature branch name"},"last_activity_at":{"type":["integer","null"],"format":"int64","description":"Last proxied request timestamp (epoch millis) for on-demand environments.\nNULL when on-demand is disabled or no traffic has been received yet."},"main_url":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"protected":{"type":"boolean","description":"When true, git pushes do NOT auto-deploy to this environment.\nDeployments must be promoted from another environment."},"sleeping":{"type":"boolean","description":"When true, the environment's containers are currently stopped due to\ninactivity (on-demand mode) and will start on the next request."},"slug":{"type":"string"},"subdomain":{"type":"string","description":"The host label stored for this environment (e.g.\n`myproject-production`). This is the prefix that is combined with the\nplatform's preview domain at request time to produce `main_url`. Edit\nthis via the rename-subdomain endpoint, not the full URL."},"updated_at":{"type":"integer","format":"int64"}}},"EnvironmentVariable":{"type":"object","description":"Environment variable","required":["key","value","is_secret"],"properties":{"is_secret":{"type":"boolean","description":"Whether this is a secret (should be encrypted)"},"key":{"type":"string","description":"Variable name"},"source_description":{"type":["string","null"],"description":"Where this env var originates from (for traceability)"},"value":{"type":"string","description":"Variable value (may be redacted for secrets)"}}},"EnvironmentVariableInfo":{"type":"object","required":["name","value","sensitive"],"properties":{"name":{"type":"string"},"sensitive":{"type":"boolean","description":"Whether this variable contains sensitive data (passwords, keys, tokens)","example":false},"value":{"type":"string"}}},"EnvironmentVariableResponse":{"type":"object","required":["id","key","created_at","updated_at","environments","include_in_preview","is_secret"],"properties":{"created_at":{"type":"integer","format":"int64"},"environments":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentInfo"}},"id":{"type":"integer","format":"int32"},"include_in_preview":{"type":"boolean","description":"Include this environment variable in preview environments"},"is_secret":{"type":"boolean","description":"Whether the variable is a write-only secret. Secrets always have\n`value: None` in responses."},"key":{"type":"string"},"updated_at":{"type":"integer","format":"int64"},"value":{"type":["string","null"],"description":"Plaintext value for non-secret vars (or `\"***\"` mask for list responses).\n`None` for secret vars — secrets are write-only."}}},"EnvironmentVariableValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"ErrorDashboardStatsQuery":{"type":"object","required":["start_time","end_time"],"properties":{"compare_to_previous":{"type":["boolean","null"]},"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"ErrorDashboardStatsResponse":{"type":"object","required":["total_errors","total_errors_previous_period","total_errors_change_percent","error_groups","error_groups_previous_period","start_time","end_time"],"properties":{"comparison_end_time":{"type":["string","null"],"format":"date-time"},"comparison_start_time":{"type":["string","null"],"format":"date-time"},"end_time":{"type":"string","format":"date-time"},"error_groups":{"type":"integer","format":"int64"},"error_groups_previous_period":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"total_errors":{"type":"integer","format":"int64"},"total_errors_change_percent":{"type":"number","format":"double"},"total_errors_previous_period":{"type":"integer","format":"int64"}}},"ErrorEventResponse":{"type":"object","required":["id","error_group_id","timestamp","created_at"],"properties":{"created_at":{"type":"string"},"data":{"description":"Full error event data (contains raw Sentry event or custom error data)"},"error_group_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int64"},"source":{"type":["string","null"],"description":"Source of the error event (e.g., \"sentry\", \"custom\", \"bugsnag\")"},"timestamp":{"type":"string"}}},"ErrorGroupResponse":{"type":"object","required":["id","title","error_type","first_seen","last_seen","total_count","status","project_id","created_at","updated_at"],"properties":{"assigned_to":{"type":["string","null"]},"created_at":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_type":{"type":"string"},"first_seen":{"type":"string"},"id":{"type":"integer","format":"int32"},"last_seen":{"type":"string"},"message_template":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"status":{"type":"string"},"title":{"type":"string"},"total_count":{"type":"integer","format":"int32"},"updated_at":{"type":"string"},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"ErrorGroupStatsResponse":{"type":"object","required":["total_groups","unresolved_groups","resolved_groups","ignored_groups"],"properties":{"ignored_groups":{"type":"integer","format":"int64"},"resolved_groups":{"type":"integer","format":"int64"},"total_groups":{"type":"integer","format":"int64"},"unresolved_groups":{"type":"integer","format":"int64"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"details":{"type":["string","null"]},"error":{"type":"string"}}},"ErrorRow":{"type":"object","required":["id","ts","error_group_id","fingerprint","error_class","stacktrace_preview","stacktrace_truncated"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_class":{"type":"string"},"error_group_id":{"type":"integer","format":"int32"},"fingerprint":{"type":"string"},"id":{"type":"integer","format":"int64"},"message":{"type":["string","null"]},"stacktrace_preview":{},"stacktrace_truncated":{"type":"boolean"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"ErrorTimeSeriesDataResponse":{"type":"object","required":["timestamp","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"ErrorTimeSeriesQuery":{"type":"object","required":["start_time","end_time"],"properties":{"bucket":{"type":"string","description":"Time bucket size (e.g., \"1h\", \"15m\", \"1d\", \"1 hour\", \"30 minutes\")","example":"1h"},"end_time":{"type":"string","format":"date-time"},"start_time":{"type":"string","format":"date-time"}}},"EventActivityBucket":{"type":"object","description":"Time bucket data point for event activity graph","required":["timestamp","count","unique_visitors"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences in this bucket"},"timestamp":{"type":"string","description":"Timestamp for this bucket (ISO 8601)"},"unique_visitors":{"type":"integer","format":"int64","description":"Number of unique visitors in this bucket"}}},"EventBreakdown":{"type":"string","enum":["country","region","city"]},"EventBrowserStats":{"type":"object","description":"Browser stats for an event","required":["browser","count","percentage"],"properties":{"browser":{"type":"string","description":"Browser name"},"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this browser"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"}}},"EventCount":{"type":"object","required":["event_name","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"event_name":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"EventCountryStats":{"type":"object","description":"Country stats for an event","required":["country","count","percentage"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this country"},"country":{"type":"string","description":"Country name"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"}}},"EventDetailQuery":{"type":"object","description":"Query parameters for event detail analytics","required":["event_name","project_id","start_date","end_date"],"properties":{"bucket_interval":{"type":["string","null"],"description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to get details for"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventDetailResponse":{"type":"object","description":"Summary response for a specific event's analytics","required":["event_name","total_count","unique_visitors","unique_sessions","activity_over_time","referrers","countries","browsers","bucket_interval"],"properties":{"activity_over_time":{"type":"array","items":{"$ref":"#/components/schemas/EventActivityBucket"},"description":"Time series data for event activity graph"},"browsers":{"type":"array","items":{"$ref":"#/components/schemas/EventBrowserStats"},"description":"Browser distribution of visitors who triggered this event"},"bucket_interval":{"type":"string","description":"Bucket interval used for time series ('hour', 'day', etc.)"},"countries":{"type":"array","items":{"$ref":"#/components/schemas/EventCountryStats"},"description":"Geographic distribution of visitors who triggered this event"},"event_name":{"type":"string","description":"The event name being analyzed"},"referrers":{"type":"array","items":{"$ref":"#/components/schemas/EventReferrerStats"},"description":"Top referrer hostnames for visitors who triggered this event"},"total_count":{"type":"integer","format":"int64","description":"Total number of times this event was triggered in the date range"},"unique_sessions":{"type":"integer","format":"int64","description":"Number of unique sessions where this event occurred"},"unique_visitors":{"type":"integer","format":"int64","description":"Number of unique visitors who triggered this event"}}},"EventEntriesQuery":{"type":"object","description":"Query parameters for the raw event entries list","required":["event_name","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to list occurrences for"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 20, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventEntriesResponse":{"type":"object","description":"Paginated response for raw event entries","required":["event_name","total_count","page","per_page","entries"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/EventEntryInfo"},"description":"Individual event occurrences, most recent first"},"event_name":{"type":"string","description":"The event name"},"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"total_count":{"type":"integer","format":"int64","description":"Total number of occurrences of this event in the date range"}}},"EventEntryInfo":{"type":"object","description":"A single raw occurrence of an event, including its custom JSON properties","required":["id","timestamp","page_path","href"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"City of the visitor at the time of the event"},"country":{"type":["string","null"],"description":"Country of the visitor at the time of the event"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"href":{"type":"string","description":"Full URL where the event was triggered"},"id":{"type":"integer","format":"int64","description":"Event row ID"},"page_path":{"type":"string","description":"Page path where the event was triggered"},"props":{"type":["object","null"],"description":"Custom event properties as JSON (null when the event carried no data)"},"session_id":{"type":["string","null"],"description":"Session ID the event belongs to (if any)"},"timestamp":{"type":"string","format":"date-time","description":"When the event occurred"},"visitor_id":{"type":["integer","null"],"format":"int32","description":"Visitor numeric ID (if known)"},"visitor_uuid":{"type":["string","null"],"description":"Visitor UUID (if known)"}}},"EventKind":{"type":"string","description":"Tag enum for filter parameters and routing. Matches the variant\ndiscriminator used by `ObservabilityEvent`.","enum":["request","span","error","revenue"]},"EventMetricsPayload":{"type":"object","required":["event_name","event_data","request_path","request_query"],"properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"event_data":{},"event_name":{"type":"string"},"fcp":{"type":["number","null"],"format":"float","description":"First Contentful Paint (milliseconds)"},"fid":{"type":["number","null"],"format":"float","description":"First Input Delay (milliseconds)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"},"language":{"type":["string","null"]},"lcp":{"type":["number","null"],"format":"float","description":"Largest Contentful Paint (milliseconds)"},"page_title":{"type":["string","null"]},"referrer":{"type":["string","null"],"description":"Referrer URL (falls back to Referer header if not provided)"},"request_path":{"type":"string"},"request_query":{"type":"string"},"screen_height":{"type":["integer","null"],"format":"int32","minimum":0},"screen_width":{"type":["integer","null"],"format":"int32","minimum":0},"ttfb":{"type":["number","null"],"format":"float","description":"Time to First Byte (milliseconds)"},"viewport_height":{"type":["integer","null"],"format":"int32","minimum":0},"viewport_width":{"type":["integer","null"],"format":"int32","minimum":0}}},"EventReferrerStats":{"type":"object","description":"Referrer stats for an event","required":["referrer","count","percentage"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this referrer"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"},"referrer":{"type":"string","description":"Referrer hostname or \"Direct\""}}},"EventTimeline":{"type":"object","required":["date","count"],"properties":{"count":{"type":"integer","format":"int64"},"date":{"type":"string","format":"date-time"}}},"EventTimelineQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"bucket_size":{"type":["string","null"],"description":"Bucket size: hour, day, or week (auto-detected if not specified)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":["string","null"]},"start_date":{"type":"string","format":"date-time"}}},"EventType":{"type":"object","required":["name","count"],"properties":{"count":{"type":"integer","format":"int64"},"name":{"type":"string"}}},"EventTypeBreakdown":{"type":"object","required":["event_type","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"event_type":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"EventTypeBreakdownQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventTypeResponse":{"type":"object","required":["event_type","description","category"],"properties":{"category":{"type":"string"},"description":{"type":"string"},"event_type":{"type":"string"}}},"EventTypesResponse":{"type":"object","required":["events","total","page","page_size"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"EventVisitorInfo":{"type":"object","description":"A visitor who triggered a specific event","required":["visitor_id","visitor_uuid","event_count","first_triggered","last_triggered"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"Visitor's city"},"country":{"type":["string","null"],"description":"Visitor's country"},"country_code":{"type":["string","null"],"description":"Visitor's country code"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"event_count":{"type":"integer","format":"int64","description":"Number of times this visitor triggered the event"},"first_triggered":{"type":"string","format":"date-time","description":"When the visitor first triggered the event in the date range"},"last_triggered":{"type":"string","format":"date-time","description":"When the visitor last triggered the event in the date range"},"referrer_hostname":{"type":["string","null"],"description":"Referrer hostname for the event"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor numeric ID"},"visitor_uuid":{"type":"string","description":"Visitor UUID"}}},"EventVisitorsQuery":{"type":"object","description":"Query parameters for event visitors list","required":["event_name","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to list visitors for"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 20, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventVisitorsResponse":{"type":"object","description":"Paginated response for event visitors","required":["event_name","total_count","page","per_page","visitors"],"properties":{"event_name":{"type":"string","description":"The event name"},"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"total_count":{"type":"integer","format":"int64","description":"Total number of unique visitors who triggered this event"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/EventVisitorInfo"},"description":"Individual visitors who triggered this event"}}},"EventsCountQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"custom_events_only":{"type":["boolean","null"],"description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventsResponse":{"type":"object","required":["events","applied_kinds"],"properties":{"applied_kinds":{"type":"array","items":{"$ref":"#/components/schemas/EventKind"},"description":"Echo of the kinds filter actually applied (server-resolved). Useful\nfor clients that pass `kinds=` empty and want to know what they got."},"events":{"type":"array","items":{"$ref":"#/components/schemas/ObservabilityEvent"}}}},"ExecBody":{"type":"object","required":["cmd"],"properties":{"cmd":{"type":"array","items":{"type":"string"}},"cwd":{"type":["string","null"]},"env":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}}},"additionalProperties":false},"ExecDetachedResponse":{"type":"object","required":["job_id"],"properties":{"job_id":{"type":"string"}}},"ExecResponse":{"type":"object","required":["exit_code","stdout","stderr"],"properties":{"exit_code":{"type":"integer","format":"int32"},"stderr":{"type":"string"},"stdout":{"type":"string"}}},"ExecuteImportRequest":{"type":"object","description":"Request to execute an import","required":["session_id","project_name","preset","directory","main_branch"],"properties":{"directory":{"type":"string","description":"Project directory","example":"."},"dry_run":{"type":["boolean","null"],"description":"Dry run mode (don't create resources)"},"main_branch":{"type":"string","description":"Main branch name","example":"main"},"preset":{"type":"string","description":"Preset to use for the project (e.g., \"nextjs\", \"express\", \"docker\")"},"project_name":{"type":"string","description":"Project name to use (overrides the name from the plan)","example":"my-app"},"session_id":{"type":"string","description":"Session ID from plan creation"}}},"ExecuteImportResponse":{"type":"object","description":"Response from import execution","required":["session_id","status","step_results"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Created deployment ID (if completed)"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Created environment ID (if completed)"},"project_id":{"type":["integer","null"],"format":"int32","description":"Created project ID (if completed)"},"session_id":{"type":"string","description":"Session ID"},"status":{"$ref":"#/components/schemas/ImportExecutionStatus","description":"Execution status"},"step_results":{"type":"array","items":{"$ref":"#/components/schemas/StepResult"},"description":"Per-step results (in execution order)"}}},"ExecuteOperationRequest":{"type":"object","required":["operation"],"properties":{"operation":{"type":"string"}}},"ExpireRequest":{"type":"object","description":"Request to set expiration on a key","required":["key","seconds"],"properties":{"key":{"type":"string","description":"The key to set expiration on","example":"session:abc"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"seconds":{"type":"integer","format":"int64","description":"Expiration time in seconds","example":3600}}},"ExpireResponse":{"type":"object","description":"Response for expire operation","required":["success"],"properties":{"success":{"type":"boolean","description":"True if expiration was set, false if key doesn't exist"}}},"ExplorerSupportResponse":{"type":"object","required":["supported","service_type","capabilities","hierarchy"],"properties":{"capabilities":{"type":"array","items":{"type":"string"},"description":"Capabilities supported by this service","example":["sql"]},"filter_schema":{"description":"JSON Schema for filter format with embedded UI hints (if supported)"},"hierarchy":{"type":"array","items":{"$ref":"#/components/schemas/HierarchyLevel"},"description":"Hierarchy levels (describes the navigation structure)"},"reason":{"type":["string","null"],"description":"Reason why explorer is not supported (if applicable)"},"service_type":{"type":"string","description":"Service type","example":"postgres"},"supported":{"type":"boolean","description":"Whether the service supports query explorer functionality","example":true}}},"ExtendTimeoutBody":{"type":"object","properties":{"duration":{"type":["integer","null"],"format":"int64","description":"`@vercel/sandbox`-compatible alternative — duration in milliseconds.\nUsed when `extra_secs` is absent.","minimum":0},"extra_secs":{"type":["integer","null"],"format":"int64","description":"Extra seconds to add to the existing `expires_at` (temps-native).","minimum":0}}},"ExternalImageResponse":{"type":"object","required":["id","project_id","image_ref","pushed_at","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"digest":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"image_ref":{"type":"string"},"metadata":{},"project_id":{"type":"integer","format":"int32"},"pushed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"size_bytes":{"type":["integer","null"],"format":"int64"},"tag":{"type":["string","null"]}}},"ExternalServiceBackupResponse":{"type":"object","description":"Response type for external service backup","required":["id","service_id","backup_id","backup_type","state","started_at","s3_location","metadata","compression_type","created_by"],"properties":{"backup_id":{"type":"integer","format":"int32"},"backup_type":{"type":"string"},"checksum":{"type":["string","null"]},"compression_type":{"type":"string"},"created_by":{"type":"integer","format":"int32"},"error_message":{"type":["string","null"]},"expires_at":{"type":["string","null"],"example":"2025-02-15T14:30:00.123Z"},"finished_at":{"type":["string","null"],"example":"2025-01-15T14:35:00.456Z"},"id":{"type":"integer","format":"int32"},"metadata":{},"s3_location":{"type":"string"},"service_id":{"type":"integer","format":"int32"},"size_bytes":{"type":["integer","null"],"format":"int64"},"started_at":{"type":"string","example":"2025-01-15T14:30:00.123Z"},"state":{"type":"string"}}},"ExternalServiceDetails":{"type":"object","required":["service","sensitive_parameters"],"properties":{"current_parameters":{"type":["object","null"],"additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"parameter_schema":{},"sensitive_parameters":{"type":"array","items":{"type":"string"},"description":"Parameter names whose values are masked in `current_parameters` and\nmay be fetched only through the audited reveal endpoint."},"service":{"$ref":"#/components/schemas/ExternalServiceInfo"}}},"ExternalServiceInfo":{"type":"object","required":["id","name","service_type","status","created_at","updated_at","topology"],"properties":{"connection_info":{"type":["string","null"]},"created_at":{"type":"string"},"error_message":{"type":["string","null"],"description":"Error message from failed initialization."},"id":{"type":"integer","format":"int32"},"members":{"type":"array","items":{"$ref":"#/components/schemas/ServiceMemberInfo"},"description":"Cluster members (empty for standalone services)."},"metrics_enabled":{"type":"boolean","description":"Whether metric collection is enabled for this service. The UI uses this\nto decide whether to poll the monitoring endpoints."},"name":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Node ID where the service runs. Null means control plane (local)."},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"},"status":{"type":"string"},"topology":{"type":"string","description":"Service topology: \"standalone\" (single container) or \"cluster\" (HA multi-member).","example":"standalone"},"updated_at":{"type":"string"},"version":{"type":["string","null"]}}},"ExternalServiceSummary":{"type":"object","description":"Summary of the external service that owns a backup. Only populated for\nexternal-service backups (Redis, Postgres, etc.); absent for control-plane\nbackups.","required":["id","name","service_type"],"properties":{"id":{"type":"integer","format":"int32","description":"Database id of the external service."},"name":{"type":"string","description":"Human-readable service name (e.g. \"redis-prod\")."},"service_type":{"type":"string","description":"Service type string (e.g. \"postgres\", \"redis\", \"mongodb\").","example":"postgres"}}},"FieldResponse":{"type":"object","required":["name","field_type","nullable"],"properties":{"field_type":{"type":"string","description":"Field type (Int32, String, Timestamp, etc.)","example":"Int64"},"name":{"type":"string","description":"Field name","example":"id"},"nullable":{"type":"boolean","description":"Whether the field is nullable","example":false}}},"FiringSeriesEntry":{"type":"object","description":"A single currently-firing series for a dynamic alert rule, snapshotted from\nthe evaluator's in-memory per-series firing map at read time (ADR-026 Phase 3).","required":["series_key","series_label"],"properties":{"alarm_id":{"type":["integer","null"],"format":"int32","description":"The open alarm's id, when one was created (absent if suppressed)."},"series_key":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"The series' label pairs, e.g. `[[\"endpoint\",\"/checkout\"],[\"region\",\"eu-west\"]]`."},"series_label":{"type":"string","description":"The human-readable joined label, e.g. `endpoint=/checkout, region=eu-west`."}}},"FlagEnvironmentResponse":{"type":"object","required":["environment_id","enabled"],"properties":{"enabled":{"type":"boolean"},"environment_id":{"type":"integer","format":"int32"},"value":{}}},"FlagListResponse":{"type":"object","description":"Note the absence of `salt`: it is never exposed. Publishing the bucketing\nsalt would let a client predict, and self-select into, a rollout cohort.","required":["flags","total","page","page_size","total_pages"],"properties":{"flags":{"type":"array","items":{"$ref":"#/components/schemas/FlagResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","description":"Total flags matching the filter, across all pages.","minimum":0},"total_pages":{"type":"integer","format":"int64","minimum":0}}},"FlagResponse":{"type":"object","required":["id","key","value_type","default_value","client_visible","created_at","updated_at","environments"],"properties":{"archived_at":{"type":["string","null"]},"client_visible":{"type":"boolean"},"created_at":{"type":"string"},"default_value":{},"description":{"type":["string","null"]},"environments":{"type":"array","items":{"$ref":"#/components/schemas/FlagEnvironmentResponse"},"description":"Per-environment overrides. Empty means the flag inherits its default\neverywhere."},"id":{"type":"integer","format":"int32"},"key":{"type":"string"},"updated_at":{"type":"string"},"value_type":{"type":"string"}}},"FlagSnapshot":{"type":"object","description":"A single flag, already resolved down to one environment. This is what the\nevaluator sees and what the SDK caches in memory.","required":["key","value_type","default_value","enabled"],"properties":{"default_value":{"description":"Served whenever evaluation cannot do better. Genuinely polymorphic by\ndesign — the surrounding struct carries the type."},"enabled":{"type":"boolean","description":"False means the kill switch is engaged for this environment."},"environment_value":{"description":"`None` means \"inherit `default_value`\"."},"key":{"type":"string"},"value_type":{"$ref":"#/components/schemas/FlagValueType"}}},"FlagSnapshotResponse":{"type":"object","required":["environment_id","flags"],"properties":{"environment_id":{"type":"integer","format":"int32"},"flags":{"type":"array","items":{"$ref":"#/components/schemas/FlagSnapshot"},"description":"Flags collapsed to what the evaluator needs, sorted by key so the\nserialized form — and therefore the ETag — is stable."}}},"FlagValueType":{"type":"string","description":"The declared type of a flag's value. Fixed at create time.","enum":["bool","string","number","json"]},"ForecastAlgorithm":{"type":"string","description":"Forecast model family.","enum":["linear","seasonal"]},"ForecastParams":{"type":"object","description":"Forecast detector parameters (stub — not yet evaluated).","required":["forecast_horizon_secs","comparator","threshold"],"properties":{"algorithm":{"$ref":"#/components/schemas/ForecastAlgorithm"},"comparator":{"$ref":"#/components/schemas/Comparator","description":"Comparator + threshold the *forecast* is checked against."},"deviations":{"type":"number","format":"double"},"forecast_horizon_secs":{"type":"integer","format":"int32","description":"How far ahead to project before checking the breach condition."},"threshold":{"type":"number","format":"double"}}},"FullError":{"type":"object","required":["id","ts","error_group_id","fingerprint","error_class"],"properties":{"data":{"description":"Full JSONB blob from `error_events.data` — stack trace, breadcrumbs,\nrequest context, everything. Schema is documented per source SDK."},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_class":{"type":"string"},"error_group_id":{"type":"integer","format":"int32"},"fingerprint":{"type":"string"},"id":{"type":"integer","format":"int64"},"message":{"type":["string","null"]},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"FullEvent":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/FullRequest"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["request"]}}}]},{"allOf":[{"$ref":"#/components/schemas/FullError"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/RevenueRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["revenue"]}}}]},{"allOf":[{"$ref":"#/components/schemas/SpanRow","description":"`SpanRow.attributes` is the truncated form; re-fetching returns\nthe same shape so the panel has a stable contract."},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["span"]}}}],"description":"`SpanRow.attributes` is the truncated form; re-fetching returns\nthe same shape so the panel has a stable contract."}],"description":"One un-truncated row, returned by the `/full/{type}/{id}` endpoint when\nthe user clicks \"Show full\". Same shape as the list rows, but with the\nraw heavy fields restored (no truncation flags) so the side panel can\nrender the long form."},"FullRequest":{"type":"object","required":["id","ts","method","host","path","status"],"properties":{"client_ip":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_group_id":{"type":["integer","null"],"format":"int32"},"host":{"type":"string"},"id":{"type":"string","description":"The request's unique `request_id` — same identity the list rows carry\n(backend-agnostic; ClickHouse rows have no serial PK)."},"latency_ms":{"type":["integer","null"],"format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"referrer":{"type":["string","null"]},"request_headers":{},"response_headers":{},"status":{"type":"integer","format":"int32"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"},"user_agent":{"type":["string","null"]}}},"FunnelMetricsResponse":{"type":"object","required":["funnel_id","funnel_name","total_entries","step_conversions","overall_conversion_rate","average_completion_time_seconds"],"properties":{"average_completion_time_seconds":{"type":"number","format":"double"},"funnel_id":{"type":"integer","format":"int32"},"funnel_name":{"type":"string"},"overall_conversion_rate":{"type":"number","format":"double"},"step_conversions":{"type":"array","items":{"$ref":"#/components/schemas/StepConversionResponse"}},"total_entries":{"type":"integer","format":"int64","minimum":0}}},"FunnelResponse":{"type":"object","required":["id","name","is_active","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"string"}}},"GatewayStatus":{"type":"object","description":"Detailed gateway container status surfaced to the settings UI.","required":["present","running","health","container_name","expected_image","drift","auto_upgrade"],"properties":{"auto_upgrade":{"type":"boolean","description":"True if `auto_upgrade` is enabled in settings."},"container_name":{"type":"string","description":"Container name."},"drift":{"type":"boolean","description":"True when `image != expected_image` and the container is present."},"expected_image":{"type":"string","description":"The image the supervisor *expects* (from settings/constant). If this\ndiffers from `image`, the UI shows a \"drift\" badge."},"health":{"type":"string","description":"Higher-level health label: \"running\" | \"restarting\" | \"crash_looping\"\n| \"stopped\" | \"missing\". UI should prefer this over `running`."},"host_port":{"type":["integer","null"],"format":"int32","description":"Host port that the container's :8080 is published on.","minimum":0},"image":{"type":["string","null"],"description":"Image reference the container was created with (e.g.\n`ghcr.io/gotempsh/temps-preview-gateway:latest`)."},"image_digest":{"type":["string","null"],"description":"Image digest if available (e.g. `sha256:…`)."},"last_error":{"type":["string","null"],"description":"Error string Docker recorded for the container (e.g. startup failure)."},"last_exit_code":{"type":["integer","null"],"format":"int64","description":"Exit code of the last run, if the container is not currently running."},"network":{"type":["string","null"],"description":"Network the container is attached to (should be `temps-sandbox-net`)."},"present":{"type":"boolean","description":"Whether the container exists at all."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Number of times Docker has restarted the container."},"running":{"type":"boolean","description":"Whether the container is currently running."},"started_at":{"type":["string","null"],"description":"ISO 8601 timestamp the container was started at, if running."}}},"GenAiEvent":{"type":"object","description":"A GenAI-related event extracted from span events.\n\nCovers `gen_ai.client.inference.operation.details` and `gen_ai.evaluation.result`\nevents per the OTel GenAI semantic conventions.","required":["span_id","trace_id","event_name","timestamp","attributes"],"properties":{"attributes":{"type":"object","description":"All event attributes.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"event_name":{"type":"string"},"span_id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"trace_id":{"type":"string"}}},"GenAiSpanDetail":{"type":"object","description":"A single GenAI span with extracted semantic convention fields.\n\nFields are aligned with the OpenTelemetry GenAI Semantic Conventions spec:\n","required":["span_id","name","kind","start_time","duration_ms","status_code","attributes"],"properties":{"agent_description":{"type":["string","null"],"description":"Agent description from `gen_ai.agent.description`."},"agent_id":{"type":["string","null"],"description":"Agent identifier from `gen_ai.agent.id`."},"agent_name":{"type":["string","null"],"description":"Agent name from `gen_ai.agent.name`."},"agent_version":{"type":["string","null"],"description":"Agent version from `gen_ai.agent.version`."},"attributes":{"type":"object","description":"All span attributes for extensibility.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"aws_bedrock_guardrail_id":{"type":["string","null"],"description":"AWS Bedrock guardrail ID from `aws.bedrock.guardrail.id`."},"aws_bedrock_knowledge_base_id":{"type":["string","null"],"description":"AWS Bedrock knowledge base ID from `aws.bedrock.knowledge_base.id`."},"azure_resource_provider_namespace":{"type":["string","null"],"description":"Azure resource provider namespace from `azure.resource_provider.namespace`."},"cache_creation_input_tokens":{"type":["integer","null"],"format":"int64","description":"Tokens written to provider cache from `gen_ai.usage.cache_creation.input_tokens`."},"cache_read_input_tokens":{"type":["integer","null"],"format":"int64","description":"Tokens served from provider cache from `gen_ai.usage.cache_read.input_tokens`."},"conversation_id":{"type":["string","null"],"description":"Unique conversation/session/thread ID from `gen_ai.conversation.id`."},"data_source_id":{"type":["string","null"],"description":"Data source identifier from `gen_ai.data_source.id`."},"duration_ms":{"type":"number","format":"double"},"embeddings_dimension_count":{"type":["integer","null"],"format":"int64","description":"Output embedding dimensions from `gen_ai.embeddings.dimension.count`."},"error_type":{"type":["string","null"],"description":"Error type from `error.type` when the span status is ERROR."},"gen_ai_model":{"type":["string","null"],"description":"The requested model from `gen_ai.request.model`."},"gen_ai_operation":{"type":["string","null"],"description":"The operation type from `gen_ai.operation.name` (e.g. \"chat\", \"embeddings\", \"execute_tool\")."},"gen_ai_response_model":{"type":["string","null"],"description":"The model that actually generated the response from `gen_ai.response.model`."},"gen_ai_system":{"type":["string","null"],"description":"The GenAI provider from `gen_ai.provider.name` (falls back to deprecated `gen_ai.system`)."},"input_messages":{"type":["string","null"],"description":"Chat history input from `gen_ai.input.messages` (opt-in, JSON string)."},"input_tokens":{"type":["integer","null"],"format":"int64"},"kind":{"$ref":"#/components/schemas/SpanKind"},"name":{"type":"string"},"openai_api_type":{"type":["string","null"],"description":"OpenAI API type from `openai.api.type` (chat_completions, responses)."},"openai_request_service_tier":{"type":["string","null"],"description":"Requested service tier from `openai.request.service_tier`."},"openai_response_service_tier":{"type":["string","null"],"description":"Actual service tier from `openai.response.service_tier`."},"openai_system_fingerprint":{"type":["string","null"],"description":"System fingerprint from `openai.response.system_fingerprint`."},"output_messages":{"type":["string","null"],"description":"Model output from `gen_ai.output.messages` (opt-in, JSON string)."},"output_tokens":{"type":["integer","null"],"format":"int64"},"output_type":{"type":["string","null"],"description":"Output content type from `gen_ai.output.type` (text, json, image, speech)."},"parent_span_id":{"type":["string","null"]},"request_choice_count":{"type":["integer","null"],"format":"int64","description":"Number of choices requested from `gen_ai.request.choice.count`."},"request_encoding_formats":{"type":["array","null"],"items":{"type":"string"},"description":"Requested encoding formats from `gen_ai.request.encoding_formats`."},"request_frequency_penalty":{"type":["number","null"],"format":"double","description":"Frequency penalty from `gen_ai.request.frequency_penalty`."},"request_max_tokens":{"type":["integer","null"],"format":"int64","description":"Max tokens from `gen_ai.request.max_tokens`."},"request_presence_penalty":{"type":["number","null"],"format":"double","description":"Presence penalty from `gen_ai.request.presence_penalty`."},"request_seed":{"type":["integer","null"],"format":"int64","description":"Seed for reproducibility from `gen_ai.request.seed`."},"request_stop_sequences":{"type":["array","null"],"items":{"type":"string"},"description":"Stop sequences from `gen_ai.request.stop_sequences`."},"request_temperature":{"type":["number","null"],"format":"double","description":"Temperature setting from `gen_ai.request.temperature`."},"request_top_k":{"type":["number","null"],"format":"double","description":"Top-k setting from `gen_ai.request.top_k`."},"request_top_p":{"type":["number","null"],"format":"double","description":"Top-p setting from `gen_ai.request.top_p`."},"response_finish_reasons":{"type":["array","null"],"items":{"type":"string"},"description":"Reasons the model stopped from `gen_ai.response.finish_reasons` (e.g. [\"stop\"])."},"response_id":{"type":["string","null"],"description":"Unique completion ID from `gen_ai.response.id` (e.g. \"chatcmpl-123\")."},"retrieval_documents":{"type":["string","null"],"description":"Retrieved documents from `gen_ai.retrieval.documents` (opt-in, JSON string)."},"retrieval_query_text":{"type":["string","null"],"description":"Retrieval query text from `gen_ai.retrieval.query.text` (opt-in)."},"server_address":{"type":["string","null"],"description":"GenAI server address from `server.address`."},"server_port":{"type":["integer","null"],"format":"int64","description":"GenAI server port from `server.port`."},"span_id":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"system_instructions":{"type":["string","null"],"description":"System instructions from `gen_ai.system_instructions` (opt-in, JSON string)."},"tool_call_arguments":{"type":["string","null"],"description":"Tool call arguments from `gen_ai.tool.call.arguments` (opt-in, JSON string)."},"tool_call_id":{"type":["string","null"],"description":"Tool call ID from `gen_ai.tool.call.id`."},"tool_call_result":{"type":["string","null"],"description":"Tool call result from `gen_ai.tool.call.result` (opt-in, JSON string)."},"tool_definitions":{"type":["string","null"],"description":"Tool definitions from `gen_ai.tool.definitions` (opt-in, JSON string)."},"tool_description":{"type":["string","null"],"description":"Tool description from `gen_ai.tool.description`."},"tool_name":{"type":["string","null"],"description":"Tool name from `gen_ai.tool.name`."},"tool_type":{"type":["string","null"],"description":"Tool type from `gen_ai.tool.type` (function, extension, datastore)."}}},"GenAiTraceDetailResponse":{"type":"object","required":["trace_id","spans","span_count","events","event_count"],"properties":{"event_count":{"type":"integer","minimum":0},"events":{"type":"array","items":{"$ref":"#/components/schemas/GenAiEvent"}},"span_count":{"type":"integer","minimum":0},"spans":{"type":"array","items":{"$ref":"#/components/schemas/GenAiSpanDetail"}},"trace_id":{"type":"string"}}},"GenAiTraceSummariesResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GenAiTraceSummary"}},"total":{"type":"integer","format":"int64","minimum":0}}},"GenAiTraceSummary":{"type":"object","description":"Summary of a GenAI conversation — aggregated from OTel spans with `gen_ai.*` attributes.","required":["trace_id","root_span_name","service_name","start_time","duration_ms","span_count","error_count"],"properties":{"duration_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"gen_ai_model":{"type":["string","null"],"description":"The requested model from `gen_ai.request.model`."},"gen_ai_operation":{"type":["string","null"],"description":"The operation type from `gen_ai.operation.name` (e.g. \"chat\", \"embeddings\")."},"gen_ai_system":{"type":["string","null"],"description":"The GenAI provider (e.g. \"openai\", \"anthropic\") from `gen_ai.provider.name`."},"root_span_name":{"type":"string"},"service_name":{"type":"string"},"span_count":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"total_cache_creation_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total cache-creation input tokens across all spans."},"total_cache_read_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total cache-read input tokens across all spans."},"total_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total input tokens across all spans in this trace."},"total_output_tokens":{"type":["integer","null"],"format":"int64","description":"Total output tokens across all spans in this trace."},"trace_id":{"type":"string"}}},"GeneralStatsQuery":{"type":"object","required":["start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"start_date":{"type":"string","format":"date-time"}}},"GeneralStatsResponse":{"type":"object","required":["total_unique_visitors","total_visits","total_page_views","total_events","total_projects","avg_bounce_rate","avg_engagement_rate","project_breakdown"],"properties":{"avg_bounce_rate":{"type":"number","format":"double"},"avg_engagement_rate":{"type":"number","format":"double"},"page_views_trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change in page views vs previous period"},"previous_page_views":{"type":["integer","null"],"format":"int64","description":"Previous period page views"},"previous_unique_visitors":{"type":["integer","null"],"format":"int64","description":"Previous period unique visitors (same duration, shifted back)"},"project_breakdown":{"type":"array","items":{"$ref":"#/components/schemas/ProjectStatsBreakdown"}},"total_events":{"type":"integer","format":"int64"},"total_page_views":{"type":"integer","format":"int64"},"total_projects":{"type":"integer","format":"int64"},"total_unique_visitors":{"type":"integer","format":"int64"},"total_visits":{"type":"integer","format":"int64"},"visitors_trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change in unique visitors vs previous period"}}},"GenerateDockerfileRequest":{"type":"object","description":"Request body for generating a Dockerfile from a preset","properties":{"build_command":{"type":["string","null"],"description":"Custom build command (overrides preset default)","example":"npm run build"},"install_command":{"type":["string","null"],"description":"Custom install command (overrides preset default)","example":"npm ci"},"output_dir":{"type":["string","null"],"description":"Output directory for static builds","example":"dist"},"package_manager":{"type":["string","null"],"description":"Package manager used by the project (npm, yarn, pnpm, bun)\nIf not provided, defaults to npm","example":"npm"},"project_name":{"type":["string","null"],"description":"Project name/slug used for container naming","example":"my-app"},"use_buildkit":{"type":"boolean","description":"Whether to use BuildKit cache mounts for faster builds"}}},"GenerateDockerfileResponse":{"type":"object","description":"Response containing a generated Dockerfile and build arguments","required":["dockerfile","build_args","preset"],"properties":{"build_args":{"type":"object","description":"Build arguments to pass to `docker build --build-arg KEY=VALUE`","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"dockerfile":{"type":"string","description":"The generated Dockerfile content"},"preset":{"type":"string","description":"The preset slug used for generation"}}},"GenerateJoinTokenResponse":{"type":"object","description":"Response returned when a join token is generated (plaintext shown once)","required":["token","message"],"properties":{"message":{"type":"string"},"token":{"type":"string","description":"The plaintext join token — shown only once, save it now"}}},"GeoLocationResponse":{"type":"object","description":"Response containing geolocation information for an IP address","required":["ip","is_eu"],"properties":{"city":{"type":["string","null"],"description":"City name","example":"Mountain View"},"country":{"type":["string","null"],"description":"Country name","example":"United States"},"country_code":{"type":["string","null"],"description":"ISO country code (2 letters)","example":"US"},"ip":{"type":"string","description":"IP address that was geolocated","example":"8.8.8.8"},"is_eu":{"type":"boolean","description":"Whether the IP is in the European Union","example":false},"latitude":{"type":["number","null"],"format":"double","description":"Latitude coordinate","example":37.386},"longitude":{"type":["number","null"],"format":"double","description":"Longitude coordinate","example":-122.0838},"region":{"type":["string","null"],"description":"Region/state name","example":"California"},"timezone":{"type":["string","null"],"description":"Timezone identifier","example":"America/Los_Angeles"}}},"GeoRestrictionsConfig":{"type":"object","description":"Geographic restrictions configuration (future feature)","properties":{"allowedCountries":{"type":"array","items":{"type":"string"},"description":"Allow traffic only from specific countries"},"blockedCountries":{"type":"array","items":{"type":"string"},"description":"Block traffic from specific countries (ISO 3166-1 alpha-2 codes)"}}},"GetDeploymentsParams":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64"},"per_page":{"type":["integer","null"],"format":"int64"}}},"GetEnvironmentVariablesQuery":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"service_id":{"type":["integer","null"],"format":"int32","description":"Required by integration-value reveals to bind the plaintext response to\nthe exact service displayed by the client."},"var_id":{"type":["integer","null"],"format":"int32","description":"Exact manual env-var row to reveal. Required by the dashboard so\nduplicate keys on disjoint environments cannot cross-reveal."}}},"GetFunnelMetricsQuery":{"type":"object","properties":{"country_code":{"type":["string","null"]},"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":["string","null"],"format":"date-time"}}},"GetOrCreateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"}}},"GetProjectSecretsQuery":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"}}},"GetProjectSessionReplaysQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"project_id":{"type":"integer","format":"int32"}}},"GetProjectSessionReplaysResponse":{"type":"object","required":["sessions","page","per_page","total_count"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}},"total_count":{"type":"integer","format":"int64","minimum":0}}},"GetRequest":{"type":"object","description":"Request to get a value by key","required":["key"],"properties":{"key":{"type":"string","description":"The key to retrieve","example":"user:123"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"GetResponse":{"type":"object","description":"Response for get operation","properties":{"value":{"description":"The value, or null if not found"}}},"GetSessionReplayResponse":{"type":"object","required":["session"],"properties":{"session":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}}},"GetUniqueEventsQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"page_size":{"type":["integer","null"],"format":"int64","minimum":0}}},"GetVisitorSessionsQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0}}},"GetVisitorSessionsResponse":{"type":"object","required":["sessions","page","per_page","total_count"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}},"total_count":{"type":"integer","minimum":0}}},"GitPushEvent":{"type":"object","description":"Git push event information that triggered the deployment","required":["repo","owner","branch","commit"],"properties":{"branch":{"type":"string","description":"Branch that was pushed"},"commit":{"type":"string","description":"Commit SHA"},"owner":{"type":"string","description":"Repository owner/organization"},"repo":{"type":"string","description":"Repository name"}}},"GitRefResponse":{"type":"object","description":"Git repository reference response","required":["url","ref"],"properties":{"path":{"type":["string","null"],"description":"Path within the repository (for monorepos)"},"ref":{"type":"string","description":"Git reference (branch, tag, or commit)"},"url":{"type":"string","description":"Git repository URL"}}},"GitSourcePlan":{"type":"object","description":"Git repository the source platform deploys from","required":["owner","repo","branch","is_public"],"properties":{"branch":{"type":"string","description":"Branch the source platform deploys"},"clone_url":{"type":["string","null"],"description":"Full clone URL, e.g. `https://github.com/owner/repo.git`"},"is_public":{"type":"boolean","description":"True when the repository is public (no credentials on the source\nplatform) — the project can then build without a git provider\nconnection."},"owner":{"type":"string","description":"Repository owner (organization or user)"},"repo":{"type":"string","description":"Repository name"}}},"GlobalConversationResponse":{"type":"object","description":"A conversation in the unified cross-project switcher: carries the project it\nbelongs to (name/slug) so the UI can show where the chat was started and\nlink back to the source.","required":["public_id","project_id","context_type","context_id","status","created_at","last_activity_at"],"properties":{"context_id":{"type":"string"},"context_type":{"type":"string"},"created_at":{"type":"string"},"last_activity_at":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":["string","null"]},"project_slug":{"type":["string","null"]},"public_id":{"type":"string"},"status":{"type":"string"},"title":{"type":["string","null"]}}},"GlobalEventStatsResponse":{"type":"object","required":["delivered","opened","clicked","bounced","complained"],"properties":{"bounce_rate":{"type":["number","null"],"format":"double"},"bounced":{"type":"integer","format":"int64","minimum":0},"click_rate":{"type":["number","null"],"format":"double"},"clicked":{"type":"integer","format":"int64","minimum":0},"complained":{"type":"integer","format":"int64","minimum":0},"delivered":{"type":"integer","format":"int64","minimum":0},"open_rate":{"type":["number","null"],"format":"double"},"opened":{"type":"integer","format":"int64","minimum":0}}},"GlobalMrrResponse":{"type":"object","required":["currency","current_mrr_minor","previous_mrr_minor"],"properties":{"change_percentage":{"type":["number","null"],"format":"double","description":"Percentage change vs 24h ago. Null when previous MRR is zero\n(no baseline to compare against)."},"currency":{"type":"string"},"current_mrr_minor":{"type":"integer","format":"int64"},"previous_mrr_minor":{"type":"integer","format":"int64","description":"MRR 24h before now, reconstructed from the event log."}}},"GlobalRecentEventResponse":{"type":"object","required":["id","project_id","project_name","occurred_at","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"mrr_minor":{"type":["integer","null"],"format":"int64"},"occurred_at":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"}}},"GlobalRevenueSummaryResponse":{"type":"object","required":["currency","current_mrr_minor","paid_last_30d_minor","refunded_last_30d_minor","paid_all_time_minor","refunded_all_time_minor","active_subscriptions","active_customers","transactions_last_30d"],"properties":{"active_customers":{"type":"integer","format":"int64"},"active_subscriptions":{"type":"integer","format":"int64"},"currency":{"type":"string"},"current_mrr_minor":{"type":"integer","format":"int64"},"paid_all_time_minor":{"type":"integer","format":"int64"},"paid_last_30d_minor":{"type":"integer","format":"int64"},"refunded_all_time_minor":{"type":"integer","format":"int64"},"refunded_last_30d_minor":{"type":"integer","format":"int64"},"transactions_last_30d":{"type":"integer","format":"int64"}}},"GroupedPageMetric":{"type":"object","required":["group_key","events"],"properties":{"cls":{"type":["number","null"],"format":"float"},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 code of the group's country. Populated for the\ngeographic dimensions (country/region/city) so clients can match map\ngeometries without name-based lookups; null otherwise."},"events":{"type":"integer","format":"int64"},"fcp":{"type":["number","null"],"format":"float"},"group_key":{"type":"string"},"inp":{"type":["number","null"],"format":"float"},"lcp":{"type":["number","null"],"format":"float"},"ttfb":{"type":["number","null"],"format":"float"}}},"GroupedPageMetricsQuery":{"allOf":[{"$ref":"#/components/schemas/SpeedSegmentFilters","description":"Segment filters — same shape as `PerformanceMetricsQuery`."},{"type":"object","required":["start_date","end_date","project_id","group_by"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"],"description":"Device type filter: \"desktop\" or \"mobile\""},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"group_by":{"type":"string"},"include_bots":{"type":["boolean","null"],"description":"Include crawler/datacenter (bot) samples. Defaults to false."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"GroupedPageMetricsResponse":{"type":"object","required":["groups","total_events","grouped_by"],"properties":{"grouped_by":{"type":"string"},"groups":{"type":"array","items":{"$ref":"#/components/schemas/GroupedPageMetric"}},"total_events":{"type":"integer","format":"int64"}}},"HasAnalyticsEventsResponse":{"type":"object","required":["has_events"],"properties":{"has_events":{"type":"boolean"}}},"HasErrorGroupsResponse":{"type":"object","required":["has_error_groups"],"properties":{"has_error_groups":{"type":"boolean"}}},"HasEventsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"HasEventsResponse":{"type":"object","required":["has_events"],"properties":{"has_events":{"type":"boolean"}}},"HasMetricsQuery":{"type":"object","required":["project_id"],"properties":{"project_id":{"type":"integer","format":"int32"}}},"HasMetricsResponse":{"type":"object","required":["has_metrics"],"properties":{"has_metrics":{"type":"boolean"}}},"HealthCheckConfiguration":{"type":"object","description":"Health check configuration","required":["port","interval","timeout","retries"],"properties":{"http_path":{"type":["string","null"],"description":"HTTP path to check (if applicable)"},"interval":{"type":"integer","format":"int32","description":"Interval between checks (seconds)","minimum":0},"port":{"type":"integer","format":"int32","description":"Port to check","minimum":0},"retries":{"type":"integer","format":"int32","description":"Number of retries before marking unhealthy","minimum":0},"timeout":{"type":"integer","format":"int32","description":"Timeout for each check (seconds)","minimum":0}}},"HealthCheckEntryResponse":{"type":"object","required":["checked_at","status"],"properties":{"checked_at":{"type":"string","description":"ISO 8601 timestamp of when the probe ran.","example":"2026-04-22T11:30:00Z"},"error_message":{"type":["string","null"],"description":"Present only when the probe failed or was degraded."},"response_time_ms":{"type":["integer","null"],"format":"int32","description":"TCP connect latency in milliseconds."},"status":{"type":"string","description":"\"operational\" | \"degraded\" | \"down\"","example":"operational"}}},"HealthResponse":{"type":"object","required":["summaries"],"properties":{"summaries":{"type":"array","items":{"$ref":"#/components/schemas/HealthSummary"}}}},"HealthStatus":{"type":"string","description":"Overall health status.","enum":["healthy","degraded","down","unknown"]},"HealthSummary":{"type":"object","description":"Pre-computed health summary for a project environment.","required":["project_id","service_name","status","uptime_pct","error_rate","p95_latency_ms","cpu_usage_pct","memory_usage_pct","computed_at"],"properties":{"computed_at":{"type":"string","format":"date-time"},"cpu_usage_pct":{"type":"number","format":"double"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_rate":{"type":"number","format":"double"},"last_deploy_at":{"type":["string","null"],"format":"date-time"},"last_deploy_id":{"type":["integer","null"],"format":"int32"},"memory_usage_pct":{"type":"number","format":"double"},"p95_latency_ms":{"type":"number","format":"double"},"project_id":{"type":"integer","format":"int32"},"service_name":{"type":"string"},"status":{"$ref":"#/components/schemas/HealthStatus"},"uptime_pct":{"type":"number","format":"double"}}},"HeartbeatApiRequest":{"type":"object","properties":{"architecture":{"type":["string","null"],"description":"Container platform of this node's Docker daemon (`linux/amd64`,\n`linux/arm64`), read from `docker info` by the agent. Absent from\npre-multi-arch agents; the stored value is then left untouched."},"capacity":{"description":"Resource capacity/usage info as JSON (cpu_usage, memory_usage, etc.)"},"containers":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ContainerInventoryItem"},"description":"Container inventory for reconciliation (sent on first heartbeat after agent startup).\nEach entry has `container_id` and `container_name` of temps-managed containers."},"labels":{"description":"Updated node labels for scheduling (allows runtime label changes)."}}},"HeartbeatResponse":{"type":"object","required":["status","message"],"properties":{"message":{"type":"string"},"status":{"type":"string"}}},"HierarchyLevel":{"type":"object","description":"Describes a level in the data source hierarchy","required":["level","name","container_type","can_list_containers","can_list_entities"],"properties":{"can_list_containers":{"type":"boolean","description":"Can list containers at this level?","example":true},"can_list_entities":{"type":"boolean","description":"Can list entities at this level?","example":false},"container_type":{"type":"string","description":"Type of container at this level","example":"database"},"level":{"type":"integer","format":"int32","description":"Level number (0 = root)","example":0,"minimum":0},"name":{"type":"string","description":"Human-readable name for this level","example":"root"}}},"HistogramSummary":{"type":"object","description":"An explicit-bucket histogram aggregated over a time bucket.\n\nCarries the reduced scalars (count/sum/min/max) plus the explicit bucket\nlayout — `bounds` (the upper bounds) and `bucket_counts` (observation counts,\nsummed element-wise across the window; length is `bounds.len() + 1`, the last\nentry being the +Inf overflow bucket). With these, a caller can reconstruct\nany quantile (e.g. p95) via cumulative-count interpolation.","required":["count","sum","bounds","bucket_counts"],"properties":{"bounds":{"type":"array","items":{"type":"number","format":"double"},"description":"Explicit bucket upper bounds (OTLP `explicit_bounds`), ascending."},"bucket_counts":{"type":"array","items":{"type":"integer","format":"int64","minimum":0},"description":"Per-bucket observation counts summed element-wise across the window.\nLength is `bounds.len() + 1` (the trailing element is the +Inf bucket)."},"count":{"type":"integer","format":"int64","description":"Total observation count summed across the bucket window.","minimum":0},"max":{"type":["number","null"],"format":"double","description":"Maximum observed value, when reported by the producer."},"min":{"type":["number","null"],"format":"double","description":"Minimum observed value, when reported by the producer."},"sum":{"type":"number","format":"double","description":"Sum of observed values across the bucket window."}}},"HostnameChange":{"type":"object","description":"A single generated-hostname change in a flatten preview/apply.","required":["kind","id","old","new"],"properties":{"id":{"type":"integer","format":"int32","description":"Row id of the affected record."},"kind":{"type":"string","description":"`\"deployment\"` or `\"environment\"`."},"new":{"type":"string"},"old":{"type":"string"}}},"HostnamePreviewResponse":{"type":"object","description":"Combined preview of a hostname-mode change.","required":["hostname_changes","dns_changes","total"],"properties":{"dns_changes":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordChange"}},"hostname_changes":{"type":"array","items":{"$ref":"#/components/schemas/HostnameChange"}},"total":{"type":"integer","minimum":0},"zone_access_ok":{"type":["boolean","null"],"description":"Whether the provider token can manage this zone (None if not checked)."}}},"HourlyPageSessions":{"type":"object","required":["timestamp","session_count","event_count","avg_duration_seconds"],"properties":{"avg_duration_seconds":{"type":"number","format":"double"},"event_count":{"type":"integer","format":"int64"},"session_count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"HourlyVisitsQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (page views), sessions (unique sessions), or visitors (unique visitors)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"HttpChallengeDebugResponse":{"type":"object","required":["domain","challenge_exists","dns_a_records","dns_aaaa_records"],"properties":{"challenge_exists":{"type":"boolean"},"challenge_token":{"type":["string","null"]},"challenge_url":{"type":["string","null"],"description":"The full URL that Let's Encrypt will try to access to validate the challenge"},"dns_a_records":{"type":"array","items":{"type":"string"},"description":"IPv4 addresses the domain points to"},"dns_aaaa_records":{"type":"array","items":{"type":"string"},"description":"IPv6 addresses the domain points to"},"dns_error":{"type":["string","null"],"description":"Any DNS resolution errors"},"domain":{"type":"string"},"validation_url":{"type":["string","null"],"description":"The ACME validation URL (internal to ACME protocol)"}}},"ImportCredentials":{"type":"object","description":"Platform-specific credentials for accessing the source system.\n\nFor platforms like Vercel and Railway, this contains the API token.\nFor self-hosted platforms like Coolify and Dokploy, this also contains\nthe `base_url` of the instance.\n\nLocal importers (Docker) can use `ImportCredentials::none()`.","properties":{"base_url":{"type":["string","null"],"description":"Base URL override (for self-hosted platforms like Coolify, Dokploy)\n\nExample: `https://coolify.example.com`"},"extra":{"type":"object","description":"Additional platform-specific parameters","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"team_id":{"type":["string","null"],"description":"Team or organization ID (for platforms with team scoping like Vercel)"},"token":{"type":["string","null"],"description":"API token / bearer token for the source platform"}}},"ImportExecutionStatus":{"type":"string","description":"Import execution status","enum":["pending","inprogress","completed","failed"]},"ImportExternalServiceRequest":{"type":"object","description":"Request to import a Docker container as a managed service","required":["name","service_type","parameters","container_id"],"properties":{"container_id":{"type":"string","description":"Container ID or name to import","example":"abc123def456"},"name":{"type":"string","description":"Name to register the service as in Temps","example":"production-database"},"parameters":{"type":"object","description":"Service configuration parameters","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute","description":"Service type"},"version":{"type":["string","null"],"description":"Optional version override"}}},"ImportOutcomeResponse":{"type":"object","required":["rows_read","inserted","updated","skipped_stale","skipped_invalid","errors"],"properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ImportRowErrorResponse"}},"inserted":{"type":"integer","minimum":0},"rows_read":{"type":"integer","minimum":0},"skipped_invalid":{"type":"integer","minimum":0},"skipped_stale":{"type":"integer","minimum":0},"updated":{"type":"integer","minimum":0}}},"ImportPlan":{"type":"object","description":"Complete import plan describing all operations to onboard a workload.\n\nThe plan is generated from a snapshot and presented to the user for review\nbefore any resources are created. Users can modify individual items\n(skip services, change actions) before approving execution.","required":["version","source","source_id","project","environment","deployment","summary","metadata"],"properties":{"additional_deployments":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentConfiguration"},"description":"Additional deployments (workers, cron jobs, etc.)"},"cost_analysis":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CostAnalysis","description":"Cost, overprovisioning, and savings analysis. Populated by importers\nthat can observe the whole source cluster (currently Kubernetes);\n`None` for container/platform imports."}]},"deployment":{"$ref":"#/components/schemas/DeploymentConfiguration","description":"Primary deployment configuration"},"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainPlan"},"description":"Custom domains to migrate"},"environment":{"$ref":"#/components/schemas/EnvironmentConfiguration","description":"Environment configuration"},"metadata":{"$ref":"#/components/schemas/PlanMetadata","description":"Plan metadata"},"project":{"$ref":"#/components/schemas/ProjectConfiguration","description":"Project configuration"},"services":{"type":"array","items":{"$ref":"#/components/schemas/ServicePlan"},"description":"Services to migrate (databases, caches, blob stores)\n\nEach service has an `action` field the user can change before execution."},"source":{"type":"string","description":"Source system this plan was generated from"},"source_id":{"type":"string","description":"Source workload / project ID in the source system"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/MigrationStep"},"description":"Ordered list of migration steps that will be executed.\n\nThis is the human-readable execution plan. Each step describes what\nwill happen, what risks are involved, and what the user should verify.\nSteps are executed in order. If a step fails, execution stops and\nalready-created resources are reported for manual cleanup."},"summary":{"$ref":"#/components/schemas/MigrationSummary","description":"Human-readable summary of the entire migration"},"version":{"type":"string","description":"Plan version for compatibility tracking"}}},"ImportRowErrorResponse":{"type":"object","required":["row","reason"],"properties":{"reason":{"type":"string"},"row":{"type":"integer","minimum":0}}},"ImportSelector":{"type":"object","description":"Selector for discovering workloads","properties":{"label_filter":{"type":["object","null"],"description":"Filter by labels/tags","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"limit":{"type":["integer","null"],"description":"Limit number of results","minimum":0},"name_pattern":{"type":["string","null"],"description":"Filter by name pattern (glob/regex)"},"status_filter":{"type":["array","null"],"items":{"type":"string"},"description":"Filter by status (running, stopped, deployed, etc.)"},"workload_type_filter":{"type":["array","null"],"items":{"type":"string"},"description":"Filter by workload type (container, function, static-site, etc.)"}}},"ImportSource":{"type":"string","description":"Import source identifier","enum":["docker","coolify","dokploy","vercel","netlify","railway","render","fly","kubernetes","caprover","portainer","kamal","custom"]},"ImportSourceCapabilities":{"type":"object","description":"Source capabilities","required":["supports_volumes","supports_networks","supports_health_checks","supports_resource_limits","supports_build","supports_services","supports_domains","supports_project_snapshot","supports_cost_analysis","requires_credentials"],"properties":{"requires_credentials":{"type":"boolean","description":"Whether this source requires API credentials (token, base URL)"},"supports_build":{"type":"boolean"},"supports_cost_analysis":{"type":"boolean","description":"Supports cluster cost + overprovisioning analysis in the plan"},"supports_domains":{"type":"boolean","description":"Supports custom domain migration"},"supports_health_checks":{"type":"boolean"},"supports_networks":{"type":"boolean"},"supports_project_snapshot":{"type":"boolean","description":"Supports full project-level snapshots"},"supports_resource_limits":{"type":"boolean"},"supports_services":{"type":"boolean","description":"Supports service migration (databases, caches, etc.)"},"supports_volumes":{"type":"boolean"}}},"ImportSourceInfo":{"type":"object","description":"Information about an import source","required":["source","name","version","available","capabilities"],"properties":{"available":{"type":"boolean","description":"Whether the source is currently available"},"capabilities":{"$ref":"#/components/schemas/ImportSourceCapabilities","description":"Capabilities"},"name":{"type":"string","description":"Human-readable name"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source identifier"},"version":{"type":"string","description":"Source version"}}},"ImportStatusResponse":{"type":"object","description":"Response with import status","required":["session_id","status","errors","warnings","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","description":"Created at timestamp"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Created deployment ID"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Created environment ID"},"errors":{"type":"array","items":{"type":"string"},"description":"Errors (if any)"},"plan":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ImportPlan","description":"Import plan"}]},"project_id":{"type":["integer","null"],"format":"int32","description":"Created project ID"},"session_id":{"type":"string","description":"Session ID"},"status":{"$ref":"#/components/schemas/ImportExecutionStatus","description":"Current status"},"updated_at":{"type":"string","format":"date-time","description":"Updated at timestamp"},"validation":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ValidationReport","description":"Validation report"}]},"warnings":{"type":"array","items":{"type":"string"},"description":"Warnings (if any)"}}},"IncidentBucket":{"type":"object","required":["bucket_start","total_incidents","minor_incidents","major_incidents","critical_incidents","resolved_incidents","active_incidents"],"properties":{"active_incidents":{"type":"integer","format":"int64"},"avg_resolution_time_minutes":{"type":["number","null"],"format":"double"},"bucket_start":{"type":"string","format":"date-time"},"critical_incidents":{"type":"integer","format":"int64"},"major_incidents":{"type":"integer","format":"int64"},"minor_incidents":{"type":"integer","format":"int64"},"resolved_incidents":{"type":"integer","format":"int64"},"total_incidents":{"type":"integer","format":"int64"}}},"IncidentBucketedResponse":{"type":"object","required":["project_id","interval","buckets"],"properties":{"buckets":{"type":"array","items":{"$ref":"#/components/schemas/IncidentBucket"}},"environment_id":{"type":["integer","null"],"format":"int32"},"interval":{"type":"string"},"project_id":{"type":"integer","format":"int32"}}},"IncidentResponse":{"type":"object","required":["id","project_id","title","severity","status","started_at","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"monitor_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"format":"date-time"},"severity":{"type":"string"},"started_at":{"type":"string","format":"date-time"},"status":{"type":"string"},"title":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"IncidentUpdateResponse":{"type":"object","required":["id","incident_id","status","message","created_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"integer","format":"int32"},"incident_id":{"type":"integer","format":"int32"},"message":{"type":"string"},"status":{"type":"string"}}},"IncrRequest":{"type":"object","description":"Request to increment a value","required":["key"],"properties":{"amount":{"type":["integer","null"],"format":"int64","description":"Amount to increment by (default: 1)"},"key":{"type":"string","description":"The key to increment","example":"counter"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"IncrResponse":{"type":"object","description":"Response for increment operation","required":["value"],"properties":{"value":{"type":"integer","format":"int64","description":"New value after increment","example":42}}},"InitAuthResponse":{"type":"object","required":["auth_url","session_token"],"properties":{"auth_url":{"type":"string"},"session_token":{"type":"string"}}},"Insight":{"type":"object","description":"An anomaly insight.","required":["id","project_id","service_name","severity","status","title","description","anomaly_ids","started_at","created_at","updated_at"],"properties":{"anomaly_ids":{"type":"array","items":{"type":"integer","format":"int64"}},"correlated_deploy_id":{"type":["integer","null"],"format":"int32"},"created_at":{"type":"string","format":"date-time"},"description":{"type":"string"},"environment":{"type":["string","null"]},"id":{"type":"integer","format":"int64"},"metric_name":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"format":"date-time"},"service_name":{"type":"string"},"severity":{"$ref":"#/components/schemas/InsightSeverity"},"started_at":{"type":"string","format":"date-time"},"status":{"$ref":"#/components/schemas/InsightStatus"},"title":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"InsightSeverity":{"type":"string","description":"Severity of an anomaly insight.","enum":["low","medium","high","critical"]},"InsightStatus":{"type":"string","description":"Status of an insight.","enum":["active","resolved"]},"InsightsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/Insight"}}}},"IntegrationResponse":{"type":"object","required":["id","project_id","provider","webhook_path_token","webhook_path","status","has_secret","created_at"],"properties":{"config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProviderConfig","description":"Typed provider config — allowlist and metered-billing mode. Null\nwhen the operator hasn't configured one yet (accept everything)."}]},"created_at":{"type":"string","format":"date-time"},"has_secret":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"last_event_at":{"type":["string","null"],"format":"date-time"},"project_id":{"type":"integer","format":"int32"},"provider":{"type":"string"},"status":{"type":"string"},"webhook_path":{"type":"string","description":"Relative path the UI can display and copy. The frontend builds\nthe full URL by prefixing its own origin."},"webhook_path_token":{"type":"string","description":"Unguessable token embedded in the public webhook URL. The full\nURL is `{api_origin}/webhooks/revenue/{provider}/{webhook_path_token}`."}}},"IpAccessControlQuery":{"type":"object","description":"Query parameters for listing IP access control rules","properties":{"action":{"type":["string","null"],"description":"Filter by action (\"block\" or \"allow\")"}}},"IpAccessControlResponse":{"type":"object","description":"Response model for IP access control rules","required":["id","ip_address","action","created_at","updated_at"],"properties":{"action":{"type":"string"},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609Z"},"created_by":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":"string"},"reason":{"type":["string","null"]},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609Z"}}},"JobStatusResponse":{"type":"object","description":"Snapshot of a background job. `status` is one of \"running\" | \"exited\"\n| \"failed\"; `exit_code` is populated only when `status == \"exited\"`.","required":["status","stdout","stderr"],"properties":{"exit_code":{"type":["integer","null"],"format":"int32"},"reason":{"type":["string","null"]},"status":{"type":"string"},"stderr":{"type":"string"},"stdout":{"type":"string"}}},"JobSummaryResponse":{"type":"object","description":"Row in the jobs list. Omits stdout/stderr so a noisy dev server doesn't\nbloat the list payload — callers drill into `GET /jobs/{id}` for the\nfull buffer.","required":["id","status","cmd","started_at"],"properties":{"cmd":{"type":"string"},"exit_code":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"reason":{"type":["string","null"]},"started_at":{"type":"string"},"status":{"type":"string"}}},"JoinTokenStatusResponse":{"type":"object","description":"Response for join token status check","required":["has_token"],"properties":{"has_token":{"type":"boolean","description":"Whether a join token has been configured"}}},"JourneyEvent":{"type":"object","description":"A single event in the visitor journey timeline","required":["id","event_type","event_name","occurred_at","is_entry","is_exit","is_bounce"],"properties":{"event_data":{"description":"Custom event properties (for custom events)"},"event_name":{"type":"string","description":"Resolved event name (event_name for custom events, event_type for system events)"},"event_type":{"type":"string","description":"Event type: \"page_view\", \"page_leave\", \"custom\", \"web_vitals\""},"id":{"type":"integer","format":"int64","description":"Event ID"},"is_bounce":{"type":"boolean","description":"Whether this was a bounce"},"is_entry":{"type":"boolean","description":"Whether this is the entry page of the session"},"is_exit":{"type":"boolean","description":"Whether this is the exit page of the session"},"occurred_at":{"type":"string","format":"date-time","description":"When the event occurred"},"page_path":{"type":["string","null"],"description":"Page path where the event happened"},"page_title":{"type":["string","null"],"description":"Page title (if available)"},"referrer":{"type":["string","null"],"description":"Referrer URL for this event"},"scroll_depth":{"type":["integer","null"],"format":"int32","description":"Scroll depth percentage (0-100)"},"session_page_number":{"type":["integer","null"],"format":"int32","description":"Page number within the session (1-indexed)"},"time_on_page":{"type":["integer","null"],"format":"int32","description":"Time spent on page in seconds (computed, not from column)"}}},"JourneySession":{"type":"object","description":"A session within the visitor journey, grouping events","required":["session_id","started_at","duration_seconds","page_views","events_count","is_bounced","is_engaged","events"],"properties":{"channel":{"type":["string","null"],"description":"Traffic source: channel (e.g. \"organic\", \"direct\", \"social\")"},"duration_seconds":{"type":"integer","format":"int64","description":"Session duration in seconds"},"ended_at":{"type":["string","null"],"format":"date-time","description":"When the session ended"},"entry_path":{"type":["string","null"],"description":"Entry page path"},"events":{"type":"array","items":{"$ref":"#/components/schemas/JourneyEvent"},"description":"Events within this session, ordered chronologically"},"events_count":{"type":"integer","format":"int64","description":"Total events in this session"},"exit_path":{"type":["string","null"],"description":"Exit page path"},"is_bounced":{"type":"boolean","description":"Whether the session was a bounce"},"is_engaged":{"type":"boolean","description":"Whether the visitor was engaged (had non-pageview events)"},"page_views":{"type":"integer","format":"int64","description":"Number of page views in this session"},"referrer":{"type":["string","null"],"description":"Traffic source: referrer URL"},"referrer_hostname":{"type":["string","null"],"description":"Traffic source: referrer hostname"},"session_id":{"type":"integer","format":"int32","description":"Session internal ID"},"started_at":{"type":"string","format":"date-time","description":"When the session started"},"utm_campaign":{"type":["string","null"],"description":"UTM campaign parameter"},"utm_medium":{"type":["string","null"],"description":"UTM medium parameter"},"utm_source":{"type":["string","null"],"description":"UTM source parameter"}}},"KeysRequest":{"type":"object","description":"Request to get keys matching a pattern","required":["pattern"],"properties":{"pattern":{"type":"string","description":"Pattern to match (supports * and ? wildcards)","example":"user:*"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"KeysResponse":{"type":"object","description":"Response for keys operation","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"},"description":"List of matching keys","example":["user:1","user:2","user:3"]}}},"KillJobBody":{"type":"object","properties":{"force":{"type":"boolean","description":"When true, sends SIGKILL immediately. Defaults to SIGTERM so the\nprocess gets a chance to flush (mirrors `Command.kill()` in\n`@vercel/sandbox`, which also accepts a signal override)."}},"additionalProperties":false},"KnownAiAgentsResponse":{"type":"object","description":"Response listing every AI agent the detector knows about.","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentDescriptor"}}}},"KvStatusResponse":{"type":"object","description":"Response for KV service status","required":["enabled","healthy"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image being used","example":"gotempsh/redis-walg:8-bookworm"},"enabled":{"type":"boolean","description":"Whether the KV service is enabled"},"healthy":{"type":"boolean","description":"Whether the underlying Redis service is healthy"},"version":{"type":["string","null"],"description":"Service version","example":"7.2"}}},"LemonSqueezyConfig":{"type":"object","properties":{"product_allowlist":{"type":"array","items":{"type":"string"}},"variant_allowlist":{"type":"array","items":{"type":"string"}}}},"LetsEncryptSettings":{"type":"object","properties":{"email":{"type":["string","null"],"default":null},"environment":{"type":"string","default":"production"}}},"LineContext":{"type":"object","description":"Raw surrounding lines for a single match (grep -C style).","required":["before","after"],"properties":{"after":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"},"description":"Lines immediately after the match, oldest-first."},"before":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"},"description":"Lines immediately before the match, oldest-first."}}},"LinkServiceRequest":{"type":"object","required":["project_id"],"properties":{"project_id":{"type":"integer","format":"int32"}}},"ListAgentsResponse":{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentConfigResponse"}},"total":{"type":"integer","minimum":0}}},"ListApiKeysQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"page_size":{"type":["integer","null"],"format":"int64","minimum":0}}},"ListAuditLogsQuery":{"type":"object","description":"Query parameters for listing audit logs.\n\nEvery field is optional — omitting one means \"don't filter on it\". Deriving\n`IntoParams` makes utoipa render them as optional query params with the\ncorrect types; the previous hand-written `params((\"operation_type\", Query,\n…))` tuples defaulted every param to `required: true, type: string`, which\nmisled both API clients and the AI `describe_api`/`call_api` tools into\nthinking all filters were mandatory.","properties":{"from":{"type":["string","null"],"format":"date-time","description":"Start timestamp (milliseconds since epoch)"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of logs to return"},"offset":{"type":["integer","null"],"format":"int32","description":"Number of logs to skip"},"operation_type":{"type":["string","null"],"description":"Filter logs by operation type (omit for all)"},"to":{"type":["string","null"],"format":"date-time","description":"End timestamp (milliseconds since epoch)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter logs by user ID (omit for all users)"}}},"ListBlobsQuery":{"type":"object","description":"Query parameters for listing blobs","properties":{"cursor":{"type":["string","null"],"description":"Continuation token for pagination"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of items to return","example":100},"prefix":{"type":["string","null"],"description":"Prefix to filter by","example":"images/"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"ListBlobsResponse":{"type":"object","description":"Response for listing blobs","required":["blobs","hasMore"],"properties":{"blobs":{"type":"array","items":{"$ref":"#/components/schemas/BlobResponse"},"description":"List of blobs"},"cursor":{"type":["string","null"],"description":"Continuation token for next page"},"hasMore":{"type":"boolean","description":"Whether there are more results","example":false}}},"ListCustomDomainsResponse":{"type":"object","required":["domains","total"],"properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/CustomDomainResponse"}},"total":{"type":"integer","minimum":0}}},"ListDeploymentTokensQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0}}},"ListDomainsResponse":{"type":"object","required":["domains","total","page","page_size"],"properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListEntitiesQuery":{"type":"object","properties":{"limit":{"type":"integer","description":"Maximum number of entities to return","example":100,"minimum":0},"token":{"type":["string","null"],"description":"Continuation token for pagination (backend-specific)"}}},"ListErrorEventsQuery":{"type":"object","properties":{"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0}}},"ListErrorGroupsQuery":{"type":"object","properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"sort_by":{"type":["string","null"]},"sort_order":{"type":"string"},"start_date":{"type":["string","null"],"format":"date-time"},"status":{"type":["string","null"]}}},"ListJobsResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/JobSummaryResponse"}}}},"ListMcpsResponse":{"type":"object","description":"Concrete list wrapper for MCP server definitions (utoipa requires non-generic types).","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/McpDefinitionResponse"}},"total":{"type":"integer","minimum":0}}},"ListOnDemandCertsResponse":{"type":"object","description":"Paginated list of on-demand cert attempts (ADR-018 §5 console \"Certificates\"\nsurface). Joined with current `domains.status`, newest first.","required":["certs","total","page","page_size"],"properties":{"certs":{"type":"array","items":{"$ref":"#/components/schemas/OnDemandCertRow"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListOrdersResponse":{"type":"object","required":["orders"],"properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/AcmeOrderResponse"}}}},"ListPresetsResponse":{"type":"object","required":["presets","total"],"properties":{"presets":{"type":"array","items":{"$ref":"#/components/schemas/PresetResponse"}},"total":{"type":"integer","minimum":0}}},"ListRunsResponse":{"type":"object","required":["items","total","page","page_size"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListSandboxesResponse":{"type":"object","description":"SDK list response: `{ sandboxes: [...], pagination: {...} }`.","required":["sandboxes","pagination"],"properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"sandboxes":{"type":"array","items":{"$ref":"#/components/schemas/SandboxInner"}}}},"ListScansQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0}}},"ListSecretsResponse":{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SecretResponse"}},"total":{"type":"integer","minimum":0}}},"ListSkillsResponse":{"type":"object","description":"Concrete list wrapper for skill definitions (utoipa requires non-generic types).","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SkillDefinitionResponse"}},"total":{"type":"integer","minimum":0}}},"ListTagsResponse":{"type":"object","description":"Response for listing tags","required":["tags","total"],"properties":{"tags":{"type":"array","items":{"type":"string"},"description":"List of available tags"},"total":{"type":"integer","description":"Total number of tags","minimum":0}}},"ListTemplatesQuery":{"type":"object","description":"Query parameters for listing templates","properties":{"featured":{"type":["boolean","null"],"description":"Only return featured templates"},"tag":{"type":["string","null"],"description":"Filter templates by tag"}}},"ListTemplatesResponse":{"type":"object","description":"Response for listing templates","required":["templates","total"],"properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/TemplateResponse"},"description":"List of templates"},"total":{"type":"integer","description":"Total number of templates","minimum":0}}},"ListVulnerabilitiesQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0},"severity":{"type":["string","null"],"example":"CRITICAL"}}},"LiveVisitorInfo":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"current_page":{"type":["string","null"],"description":"Most recent page path visited by this visitor"},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"LiveVisitorsListResponse":{"type":"object","required":["total_count","visitors","window_minutes"],"properties":{"total_count":{"type":"integer","format":"int64"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/LiveVisitorInfo"}},"window_minutes":{"type":"integer","format":"int32"}}},"LocationCount":{"type":"object","required":["location","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"location":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"LocationGranularity":{"type":"string","enum":["country","region","city"]},"LocationInfo":{"type":"object","properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"region":{"type":["string","null"]}}},"LogLevel":{"type":"string","description":"Normalized log level","enum":["TRACE","DEBUG","INFO","WARN","ERROR"]},"LogRecord":{"type":"object","description":"A single log record ready for storage.","required":["project_id","resource","timestamp","observed_timestamp","severity","severity_text","body","attributes"],"properties":{"attributes":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"body":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"observed_timestamp":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"resource":{"$ref":"#/components/schemas/ResourceInfo"},"severity":{"$ref":"#/components/schemas/LogSeverity"},"severity_text":{"type":"string"},"span_id":{"type":["string","null"]},"timestamp":{"type":"string","format":"date-time"},"trace_id":{"type":["string","null"]}}},"LogSearchLine":{"type":"object","description":"A single line in search results","required":["timestamp","level","service","message","chunk_id","line_offset"],"properties":{"chunk_id":{"type":"string"},"container_id":{"type":"string","description":"Container this line came from — lets the UI tag/group lines by container\nin a combined (\"show all\") multi-container view."},"context":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LineContext","description":"Raw surrounding lines (grep -C). `None` unless `context_lines > 0` was\nrequested. Overlapping windows between nearby matches are merged: the\nshared neighbors appear on the earlier match only, so the frontend can\nrender one continuous block without duplicated lines."}]},"deploy_id":{"type":["integer","null"],"format":"int32"},"fields":{},"level":{"$ref":"#/components/schemas/LogLevel"},"line_offset":{"type":"integer","format":"int32"},"message":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Worker node the line came from (`None` = control-plane-local)."},"node_name":{"type":["string","null"],"description":"Human-readable node name for display."},"service":{"type":"string"},"timestamp":{"type":"string"}}},"LogSeverity":{"type":"string","description":"Log severity level (simplified from OTel's 24 levels).","enum":["TRACE","DEBUG","INFO","WARN","ERROR","FATAL"]},"LogSource":{"type":"object","description":"A distinct log source (container) seen in the queried scope. Used to populate\nthe history filter dropdowns with the *full* set of containers/nodes for the\nproject + env + deployment + time window — independent of the active\ncontainer/node/service filter, so the user can switch between them.","required":["container_id","service"],"properties":{"container_id":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32"},"node_name":{"type":["string","null"]},"service":{"type":"string"}}},"LogStream":{"type":"string","description":"Log output stream","enum":["stdout","stderr"]},"LoginRequest":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"}}},"LogsQuery":{"type":"object","properties":{"tail":{"type":["integer","null"],"description":"Number of lines to return from the tail. Defaults to 200, capped at 2000.","minimum":0}}},"LogsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/LogRecord"}}}},"ManagedDomainResponse":{"type":"object","description":"Managed domain response","required":["id","provider_id","domain","auto_manage","verified","generated_hostname_mode","sync_generated_records","created_at","updated_at"],"properties":{"auto_manage":{"type":"boolean"},"created_at":{"type":"string"},"domain":{"type":"string"},"generated_hostname_mode":{"type":"string","description":"Generated hostname layout: `\"standard\"` or `\"flat\"`."},"id":{"type":"integer","format":"int32"},"provider_id":{"type":"integer","format":"int32"},"sync_generated_records":{"type":"boolean","description":"Whether generated hostnames are reconciled into the provider's DNS zone."},"updated_at":{"type":"string"},"verification_error":{"type":["string","null"]},"verified":{"type":"boolean"},"verified_at":{"type":["string","null"]},"zone_access_error":{"type":["string","null"],"description":"Detail for a failed zone-access check."},"zone_access_ok":{"type":["boolean","null"],"description":"Last token zone-access check: `Some(true)`/`Some(false)`/`None` (unchecked)."},"zone_id":{"type":["string","null"]}}},"ManualAction":{"type":"object","description":"A manual action the user must perform outside of the automated migration","required":["timing","description","reason"],"properties":{"description":{"type":"string","description":"Human-readable description"},"reason":{"type":"string","description":"Why this can't be automated"},"timing":{"$ref":"#/components/schemas/ManualActionTiming","description":"When this action needs to happen"}}},"ManualActionTiming":{"type":"string","description":"When a manual action needs to happen relative to migration","enum":["before-migration","after-migration","within-hours"]},"McpDefinitionResponse":{"type":"object","required":["id","slug","name","config","created_at","updated_at"],"properties":{"config":{"type":"object"},"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"MessageContent":{"oneOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/components/schemas/ContentPart"}}]},"MessagePart":{"oneOf":[{"type":"object","required":["text","type"],"properties":{"text":{"type":"string"},"type":{"type":"string","enum":["text"]}}},{"type":"object","required":["tool","type"],"properties":{"tool":{"$ref":"#/components/schemas/ToolInfo"},"type":{"type":"string","enum":["tool"]}}}],"description":"One ordered segment of an assistant turn: a chunk of prose, or a tool\ninvocation. Mirrors the `metadata.parts` persisted by the chat service."},"MessageResponse":{"type":"object","required":["role","content","created_at"],"properties":{"content":{"type":"string"},"created_at":{"type":"string"},"parts":{"type":["array","null"],"items":{"$ref":"#/components/schemas/MessagePart"},"description":"Ordered render segments (text / tool, in the order they occurred) so a\nreloaded chat shows the same interleaving as the live stream. Absent for\nolder messages persisted before parts were tracked; the client then falls\nback to `tools` (rendered first) + `content`."},"role":{"type":"string"},"tools":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ToolInfo"},"description":"Tools the assistant ran on this turn (persisted in message metadata), so\nthe chat replays its tool work after a reload. Absent for plain turns."}}},"MeteredMode":{"type":"string","description":"How to treat metered-billing subscriptions when computing MRR.\n\n* `DeriveFromInvoices` (default): ignore the subscription row's\n `mrr_minor` for metered items and rely on the per-invoice\n [`NormalizedEventType::MrrRealized`] events instead. Correct for\n pure-metered, hybrid, tiered, and flat — recommended.\n* `UseSubscription`: trust whatever MRR the subscription parser\n returns (0 for metered). Legacy behavior.\n* `Ignore`: drop metered subscriptions from MRR entirely.","enum":["derive_from_invoices","use_subscription","ignore"]},"MetricAggregation":{"oneOf":[{"type":"string","description":"Arithmetic mean of the scalar value in each bucket. The default.","enum":["avg"]},{"type":"string","description":"Sum of the scalar value in each bucket.","enum":["sum"]},{"type":"string","description":"Minimum scalar value in each bucket.","enum":["min"]},{"type":"string","description":"Maximum scalar value in each bucket.","enum":["max"]},{"type":"string","description":"Number of points in each bucket.","enum":["count"]},{"type":"string","description":"Per-second rate of change of a cumulative monotonic counter, computed as\n`(max - min) / window_seconds` within each bucket. Non-monotonic series\nfall back to a simple delta.","enum":["rate_per_sec"]},{"type":"object","description":"A quantile of the scalar value in each bucket. The carried `f64` is the\nrequested quantile in `[0.0, 1.0]`.","required":["quantile"],"properties":{"quantile":{"type":"number","format":"double","description":"A quantile of the scalar value in each bucket. The carried `f64` is the\nrequested quantile in `[0.0, 1.0]`."}}}],"description":"The aggregation applied when reducing raw metric points into a time bucket.\n\nStore-neutral: every storage backend (ClickHouse today, TimescaleDB later)\nmust be able to satisfy this contract. `Quantile(q)` carries the requested\nquantile in `[0.0, 1.0]` (e.g. `0.95` for p95)."},"MetricBucket":{"type":"object","description":"A time-bucketed metric aggregate for chart display.\n\nStore-neutral response contract. The legacy scalar fields\n(`avg_value`/`min_value`/`max_value`/`count`) are always populated for chart\nback-compat. The richer fields describe the explicitly-requested\n[`MetricAggregation`] (`value`), optional `quantiles`, an optional\n`histogram_summary`, and a `series_key` identifying the label-set when the\nquery used `group_by`.","required":["bucket","avg_value","min_value","max_value","count"],"properties":{"avg_value":{"type":"number","format":"double"},"bucket":{"type":"string","format":"date-time"},"count":{"type":"integer","format":"int64"},"histogram_summary":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/HistogramSummary","description":"A reduced histogram summary when the bucketed metric is a histogram."}]},"max_value":{"type":"number","format":"double"},"min_value":{"type":"number","format":"double"},"quantiles":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"number","format":"double"},{"type":"number","format":"double"}]},"description":"Computed quantile/value pairs `(quantile, value)` when the query asked for\nquantile aggregation; otherwise empty."},"series_key":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"The label-set this bucket belongs to, as ordered `(key, value)` pairs,\nwhen the query grouped by labels. Empty/`None` = the single ungrouped\naggregate stream."},"value":{"type":"number","format":"double","description":"The value of the requested [`MetricAggregation`] for this bucket. For the\ndefault `Avg` aggregation this equals `avg_value`. `#[serde(default)]` so\npre-existing payloads (which only carried avg/min/max/count) still parse."}}},"MetricDataPoint":{"type":"object","description":"A single `(timestamp, value)` data point in a metric series.","required":["time","value"],"properties":{"time":{"type":"string","description":"ISO 8601 timestamp with `Z` suffix."},"value":{"type":"number","format":"double","description":"Metric value at this bucket."}}},"MetricType":{"type":"string","description":"The type of an OTel metric.","enum":["gauge","sum","histogram","exponential_histogram","summary"]},"MetricsOverTimeResponse":{"type":"object","required":["timestamps","ttfb","lcp","fid","fcp","cls","inp"],"properties":{"cls":{"type":"array","items":{"type":["number","null"],"format":"float"}},"cls_p75":{"type":["number","null"],"format":"float"},"cls_p90":{"type":["number","null"],"format":"float"},"cls_p95":{"type":["number","null"],"format":"float"},"cls_p99":{"type":["number","null"],"format":"float"},"fcp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"fcp_p75":{"type":["number","null"],"format":"float"},"fcp_p90":{"type":["number","null"],"format":"float"},"fcp_p95":{"type":["number","null"],"format":"float"},"fcp_p99":{"type":["number","null"],"format":"float"},"fid":{"type":"array","items":{"type":["number","null"],"format":"float"}},"fid_p75":{"type":["number","null"],"format":"float"},"fid_p90":{"type":["number","null"],"format":"float"},"fid_p95":{"type":["number","null"],"format":"float"},"fid_p99":{"type":["number","null"],"format":"float"},"inp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"inp_p75":{"type":["number","null"],"format":"float"},"inp_p90":{"type":["number","null"],"format":"float"},"inp_p95":{"type":["number","null"],"format":"float"},"inp_p99":{"type":["number","null"],"format":"float"},"lcp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"lcp_p75":{"type":["number","null"],"format":"float"},"lcp_p90":{"type":["number","null"],"format":"float"},"lcp_p95":{"type":["number","null"],"format":"float"},"lcp_p99":{"type":["number","null"],"format":"float"},"timestamps":{"type":"array","items":{"type":"string"}},"ttfb":{"type":"array","items":{"type":["number","null"],"format":"float"}},"ttfb_p75":{"type":["number","null"],"format":"float"},"ttfb_p90":{"type":["number","null"],"format":"float"},"ttfb_p95":{"type":["number","null"],"format":"float"},"ttfb_p99":{"type":["number","null"],"format":"float"}}},"MetricsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"MetricsRangeQuery":{"type":"object","description":"Query params for range metric queries.","required":["metric"],"properties":{"metric":{"type":"string","description":"Metric name, e.g. `\"pg.connections_active\"`."},"percentile":{"type":["number","null"],"format":"double","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile."},"range":{"type":"string","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`."}}},"MetricsStatusResponse":{"type":"object","description":"Freshness status: when metrics were last received for this service.","properties":{"last_received_at":{"type":["string","null"],"description":"ISO 8601 timestamp of the most recent metric row, or null if none yet."}}},"MetricsStoreKind":{"type":"string","description":"Which storage backend to use for the MetricsStore.","enum":["timescale_db","click_house"]},"MetricsSummaryResponse":{"type":"object","required":["currency","current_mrr_minor","current_arr_minor","active_subscriptions","active_customers","churned_last_30d","arpu_minor"],"properties":{"active_customers":{"type":"integer","format":"int64"},"active_subscriptions":{"type":"integer","format":"int64"},"arpu_minor":{"type":"integer","format":"int64"},"churned_last_30d":{"type":"integer","format":"int64"},"currency":{"type":"string"},"current_arr_minor":{"type":"integer","format":"int64"},"current_mrr_minor":{"type":"integer","format":"int64"}}},"MfaRequiredResponse":{"type":"object","required":["requires_mfa","session_token"],"properties":{"requires_mfa":{"type":"boolean"},"session_token":{"type":"string"}}},"MfaSetupResponse":{"type":"object","required":["secret_key","qr_code","recovery_codes"],"properties":{"qr_code":{"type":"string"},"recovery_codes":{"type":"array","items":{"type":"string"}},"secret_key":{"type":"string"}}},"MfaVerificationRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"MigrationStep":{"type":"object","description":"A single step in the migration execution plan.\n\nSteps are presented to the user before execution so they know exactly\nwhat will happen. During execution, each step runs in order and reports\nits outcome before proceeding to the next.","required":["order","id","title","description","resource_type","risk","skippable","reversible"],"properties":{"data_implications":{"type":"array","items":{"$ref":"#/components/schemas/DataImplication"},"description":"Data implications — what could go wrong or what the user needs to know"},"description":{"type":"string","description":"Detailed description of what this step does"},"estimated_duration":{"type":["string","null"],"description":"Estimated duration hint (e.g., \"< 1 second\", \"10-30 seconds\")"},"id":{"type":"string","description":"Machine-readable step identifier (e.g., \"create-project\", \"create-service-postgres\")"},"order":{"type":"integer","description":"Step number (1-based, for display)","minimum":0},"post_conditions":{"type":"array","items":{"type":"string"},"description":"Things the user should verify AFTER this step completes"},"pre_conditions":{"type":"array","items":{"type":"string"},"description":"Things the user should verify BEFORE this step runs"},"resource_type":{"$ref":"#/components/schemas/StepResourceType","description":"What kind of resource this step creates/modifies"},"reversible":{"type":"boolean","description":"Whether this step is reversible (can be cleaned up on failure)"},"risk":{"$ref":"#/components/schemas/RiskLevel","description":"Risk level for this step"},"skippable":{"type":"boolean","description":"Whether this step can be skipped by the user"},"skipped":{"type":"boolean","description":"Whether the user has chosen to skip this step (set during review)"},"title":{"type":"string","description":"Human-readable title (e.g., \"Create project 'my-app'\")"}}},"MigrationSummary":{"type":"object","description":"Human-readable summary of the entire migration plan","required":["headline","overall_risk","resource_counts"],"properties":{"critical_warnings":{"type":"array","items":{"type":"string"},"description":"Critical warnings that must be acknowledged before proceeding.\nThese are the most important things the user needs to know."},"headline":{"type":"string","description":"One-line summary (e.g., \"Migrate 'my-app' from Vercel with 1 database, 2 domains\")"},"manual_actions_required":{"type":"array","items":{"$ref":"#/components/schemas/ManualAction"},"description":"Manual actions the user must perform (before or after migration)"},"overall_risk":{"$ref":"#/components/schemas/RiskLevel","description":"Overall risk assessment for the migration"},"resource_counts":{"$ref":"#/components/schemas/ResourceCounts","description":"Resource counts for quick overview"},"unsupported_features":{"type":"array","items":{"$ref":"#/components/schemas/UnsupportedFeature"},"description":"Features from the source platform that cannot be migrated"}}},"MintEnrollmentTokenRequest":{"type":"object","properties":{"bound_node_name":{"type":["string","null"],"description":"Optional: restrict the token to register one specific node name."},"max_uses":{"type":["integer","null"],"format":"int32","description":"Maximum registrations this token may authorize (default 1)."},"ttl_secs":{"type":["integer","null"],"format":"int64","description":"Time-to-live in seconds (default 3600 = 1h)."}}},"MintEnrollmentTokenResponse":{"type":"object","required":["id","token","expires_at","max_uses","message"],"properties":{"ca_fingerprint":{"type":["string","null"],"description":"SHA-256 fingerprint of the cluster CA (if mTLS is set up). Pass it to the\nworker as `temps join --ca-fingerprint ` to verify the CA on join."},"expires_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"max_uses":{"type":"integer","format":"int32"},"message":{"type":"string"},"token":{"type":"string","description":"The plaintext enrollment token — shown only once, save it now."}}},"MiscResult":{"type":"object","description":"Miscellaneous validation result","required":["is_disposable","is_role_account","is_b2c"],"properties":{"gravatar_url":{"type":["string","null"],"description":"Gravatar URL if available"},"is_b2c":{"type":"boolean","description":"Whether the email provider is a B2C (consumer) email provider"},"is_disposable":{"type":"boolean","description":"Whether the email is from a disposable email provider"},"is_role_account":{"type":"boolean","description":"Whether the email is a role-based account (e.g., admin@, info@)"}}},"MkdirBody":{"type":"object","required":["path"],"properties":{"path":{"type":"string"}},"additionalProperties":false},"ModelInfo":{"type":"object","required":["id","object","owned_by"],"properties":{"id":{"type":"string"},"object":{"type":"string"},"owned_by":{"type":"string"}}},"ModelListResponse":{"type":"object","required":["object","data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ModelInfo"}},"object":{"type":"string"}}},"ModelPricing":{"type":"object","description":"Pricing for a single model, all values in USD per 1M tokens.\nFields are optional because not every provider supports every pricing tier.","required":["model","display_name","provider","input_per_million","output_per_million"],"properties":{"batch_input_per_million":{"type":["number","null"],"format":"double","description":"Batch API input cost per 1M tokens (if provider offers batch pricing)"},"batch_output_per_million":{"type":["number","null"],"format":"double","description":"Batch API output cost per 1M tokens"},"cache_hit_per_million":{"type":["number","null"],"format":"double","description":"Cache hit / refresh cost per 1M tokens"},"cache_write_1h_per_million":{"type":["number","null"],"format":"double","description":"1-hour cache write cost per 1M tokens"},"cache_write_5m_per_million":{"type":["number","null"],"format":"double","description":"5-minute cache write cost per 1M tokens (Anthropic-style prompt caching)"},"deprecated":{"type":"boolean","description":"Whether the model is deprecated"},"display_name":{"type":"string","description":"Human-readable model name (e.g. \"Claude Sonnet 4.6\")"},"input_per_million":{"type":"number","format":"double","description":"Base input token cost per 1M tokens"},"model":{"type":"string","description":"Model identifier (e.g. \"gpt-5.4\", \"claude-sonnet-4-6\")"},"output_per_million":{"type":"number","format":"double","description":"Output token cost per 1M tokens"},"provider":{"type":"string","description":"Provider ID (e.g. \"openai\", \"anthropic\")"}}},"ModelUsage":{"type":"object","required":["model","provider","request_count","input_tokens","output_tokens","total_tokens","avg_latency_ms"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"input_tokens":{"type":"integer","format":"int64"},"model":{"type":"string"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"MonitorResponse":{"type":"object","required":["id","project_id","name","monitor_type","monitor_url","check_interval_seconds","is_active","created_at","updated_at"],"properties":{"check_interval_seconds":{"type":"integer","format":"int32"},"check_path":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"monitor_type":{"type":"string"},"monitor_url":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time"}}},"MonitorStatus":{"type":"object","required":["monitor","current_status","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["integer","null"],"format":"int32"},"current_status":{"type":"string"},"monitor":{"$ref":"#/components/schemas/MonitorResponse"},"uptime_percentage":{"type":"number","format":"double"}}},"MonitoringSettings":{"type":"object","description":"Global metrics observability configuration.\n\nControls whether the MetricsScraper and AlertEvaluator background tasks\nare active, which storage backend they write to, and how long data is kept\nat each retention tier.","properties":{"clickhouse_url":{"type":["string","null"],"description":"ClickHouse DSN (legacy, optional). The runtime metrics store is built\nfrom the `TEMPS_CLICKHOUSE_*` env vars, never from this field; it is\nretained for compatibility and operator reference only.\nExample: `\"http://localhost:8123\"`.","default":null},"enabled":{"type":"boolean","description":"Enable or disable all metrics collection (scraping + alerting).\nDefaults to `false` so new installs don't write to TimescaleDB until\nan operator explicitly enables the feature.","default":false},"retention_daily_years":{"type":"integer","format":"int32","description":"How many years of daily-aggregate data to keep (converted to days internally).","default":2,"example":2,"maximum":10,"minimum":1},"retention_hourly_days":{"type":"integer","format":"int32","description":"How many days of hourly-aggregate data to keep.","default":90,"example":90,"minimum":1},"retention_raw_days":{"type":"integer","format":"int32","description":"How many days of raw (30 s resolution) metric data to keep.","default":7,"example":7,"minimum":1},"scrape_interval_secs":{"type":"integer","format":"int64","description":"How often the MetricsScraper collects data from all sources, in seconds.\nMinimum effective value is 10 s; values below that are clamped at runtime.","default":30,"example":30,"minimum":10},"store":{"oneOf":[{"$ref":"#/components/schemas/MetricsStoreKind","description":"Storage backend for metric data."}],"default":"timescale_db"}}},"MonitoringSettingsMasked":{"type":"object","description":"Monitoring settings with the ClickHouse DSN masked.\n\n`clickhouse_url` can embed credentials (`http://user:pass@host`), so it is\nreported only as a boolean (`clickhouse_url_set`) rather than echoed back —\nconsistent with how the DNS API key and Docker registry password are masked.","required":["enabled","store","scrape_interval_secs","retention_raw_days","retention_hourly_days","retention_daily_years","clickhouse_url_set"],"properties":{"clickhouse_url_set":{"type":"boolean","description":"True when a ClickHouse DSN is configured. The DSN itself is never\nreturned over HTTP because it may contain credentials."},"enabled":{"type":"boolean"},"retention_daily_years":{"type":"integer","format":"int32","minimum":0},"retention_hourly_days":{"type":"integer","format":"int32","minimum":0},"retention_raw_days":{"type":"integer","format":"int32","minimum":0},"scrape_interval_secs":{"type":"integer","format":"int64","minimum":0},"store":{"$ref":"#/components/schemas/MetricsStoreKind"}}},"MrrBucketResponse":{"type":"object","required":["bucket","mrr_minor","charge_total_minor","refund_total_minor","charge_count"],"properties":{"bucket":{"type":"string","format":"date-time"},"charge_count":{"type":"integer","format":"int64"},"charge_total_minor":{"type":"integer","format":"int64"},"mrr_minor":{"type":"integer","format":"int64"},"refund_total_minor":{"type":"integer","format":"int64"}}},"MultiNodeSettings":{"type":"object","description":"Multi-node cluster settings","properties":{"cluster_ca_cert_pem":{"type":["string","null"],"description":"Per-cluster CA certificate (PEM) for multi-node mTLS (ADR-020 WS-2.1).\nPublic — distributed to nodes as the trust root and used by the control\nplane as the root for verifying agent server certs. Minted lazily on the\nfirst CSR-bearing registration.","default":null},"cluster_ca_key_encrypted":{"type":["string","null"],"description":"Per-cluster CA private key, AES-256-GCM ciphertext (EncryptionService).\nSECRET — never returned over HTTP (elided in the masked response).","default":null},"join_token_hash":{"type":["string","null"],"description":"SHA-256 hash of the join token (never store plaintext)","default":null},"legacy_shared_token_enabled":{"type":"boolean","description":"Whether the legacy single shared join token is still accepted for node\nregistration (ADR-020 WS-1.1). Defaults to `true` so existing clusters\nkeep working on upgrade; fresh installs should set it `false` and rely on\nshort-lived, single-use enrollment tokens instead.","default":true},"node_cpu_alert_percent":{"type":["number","null"],"format":"double","description":"CPU-usage percent above which a worker node raises a resource alert\n(ADR-020 / monitoring). `None` disables CPU alerting. Default 90.","default":90.0},"node_disk_alert_percent":{"type":["number","null"],"format":"double","description":"Disk-usage percent above which a worker node raises a resource alert.\n`None` disables disk alerting. Default 90.","default":90.0},"node_memory_alert_percent":{"type":["number","null"],"format":"double","description":"Memory-usage percent above which a worker node raises a resource alert.\n`None` disables memory alerting. Default 90.","default":90.0},"private_address":{"type":["string","null"],"description":"Private/WireGuard IP address of the control plane node.\nUsed by remote worker nodes to reach services (databases, etc.) running on the control plane.\nSet via `--private-address` or `TEMPS_PRIVATE_ADDRESS`.","default":null},"require_mtls":{"type":"boolean","description":"Whether to enforce multi-node mTLS (ADR-020 WS-2.1). When `false`\n(default), the control plane ignores join-time CSRs and nodes keep\nserving plaintext HTTP — zero behavior change. When `true`, the CP signs\nnode CSRs, nodes serve mutual TLS, and every CP→agent call uses the\ncluster client cert. Observe-then-enforce: flip this on only once all\nworkers have re-enrolled with certs.","default":false}}},"MultiNodeSettingsMasked":{"type":"object","description":"Multi-node settings with `join_token_hash` elided.","required":["has_join_token","require_mtls","legacy_shared_token_enabled"],"properties":{"cluster_ca_fingerprint":{"type":["string","null"],"description":"SHA-256 fingerprint of the cluster CA certificate (public — operators can\nverify it out of band; the CA private key is never exposed)."},"has_join_token":{"type":"boolean"},"legacy_shared_token_enabled":{"type":"boolean","description":"Whether the deprecated shared join token is still accepted."},"node_cpu_alert_percent":{"type":["number","null"],"format":"double","description":"Node resource-alert thresholds (percent); `None` = that alert disabled."},"node_disk_alert_percent":{"type":["number","null"],"format":"double"},"node_memory_alert_percent":{"type":["number","null"],"format":"double"},"private_address":{"type":["string","null"]},"require_mtls":{"type":"boolean","description":"Whether control-plane↔agent mutual TLS is enforced."}}},"MxResult":{"type":"object","description":"MX (Mail Exchange) validation result","required":["accepts_mail","records"],"properties":{"accepts_mail":{"type":"boolean","description":"Whether the domain accepts mail"},"error":{"type":["string","null"],"description":"Error message if MX lookup failed"},"records":{"type":"array","items":{"type":"string"},"description":"List of MX records for the domain","example":["alt1.gmail-smtp-in.l.google.com.","gmail-smtp-in.l.google.com."]}}},"NavEntry":{"type":"object","description":"A navigation entry that the plugin contributes to the Temps UI.","required":["label","icon","section","path","order"],"properties":{"icon":{"type":"string","description":"Lucide icon name (e.g., \"puzzle\", \"database\", \"activity\")"},"label":{"type":"string","description":"Display label in the sidebar"},"order":{"type":"integer","format":"int32","description":"Sort order within the section (lower = higher in list)","minimum":0},"path":{"type":"string","description":"Client-side route path (e.g., \"/my-plugin\")"},"section":{"$ref":"#/components/schemas/NavSection","description":"Which sidebar section this entry belongs to"}}},"NavSection":{"type":"string","description":"Where the plugin's nav entry appears in the Temps UI sidebar.","enum":["platform","settings","project"]},"NetworkConfiguration":{"type":"object","description":"Network configuration","required":["mode","dns_servers"],"properties":{"dns_servers":{"type":"array","items":{"type":"string"},"description":"DNS servers"},"hostname":{"type":["string","null"],"description":"Hostname"},"mode":{"$ref":"#/components/schemas/NetworkMode","description":"Network mode"}}},"NetworkMode":{"oneOf":[{"type":"string","enum":["bridge"]},{"type":"string","enum":["host"]},{"type":"string","enum":["none"]},{"type":"object","required":["custom"],"properties":{"custom":{"type":"string"}}}],"description":"Network mode"},"NixpacksPresetConfig":{"type":"object","description":"Configuration for Nixpacks preset\nNixpacks provider and inline build-plan configuration.","properties":{"nixpacksConfig":{"type":["string","null"],"description":"Optional inline nixpacks.toml contents."},"providers":{"type":"array","items":{"$ref":"#/components/schemas/NixpacksProvider"},"description":"Ordered Nixpacks providers. Empty means repository config or auto-detect;\ninclude `...` to combine auto-detection with explicit providers."}}},"NixpacksProvider":{"type":"string","description":"A Nixpacks build provider.\n\n`Auto` serializes as the native Nixpacks `...` marker, which includes the\nprovider detected from the project alongside any explicitly listed\nproviders.","enum":["...","node","python","rust","go","java","php","ruby","deno","elixir","csharp","fsharp","dart","swift","zig","scala","haskell","clojure","crystal","cobol","gleam","lunatic","scheme","static"]},"NodeContainerListResponse":{"type":"object","required":["containers","total"],"properties":{"containers":{"type":"array","items":{"$ref":"#/components/schemas/NodeContainerResponse"}},"total":{"type":"integer","minimum":0}}},"NodeContainerResponse":{"type":"object","description":"A container running on a specific node, enriched with project/environment context.","required":["container_id","container_name","image_name","status","created_at","deployment_id","project_id","project_name","environment_id","environment_name"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"created_at":{"type":"string"},"deployment_id":{"type":"integer","format":"int32"},"environment_id":{"type":"integer","format":"int32"},"environment_name":{"type":"string"},"image_name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"status":{"type":"string"}}},"NodeCostInfo":{"type":"object","description":"One cluster node with capacity and (when priceable) a cost estimate","required":["name","cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"CPU capacity in millicores"},"instance_type":{"type":["string","null"],"description":"Instance type from `node.kubernetes.io/instance-type` (e.g. \"m5.xlarge\")"},"memory_mb":{"type":"integer","format":"int64","description":"Memory capacity in MB"},"monthly_usd":{"type":["number","null"],"format":"double","description":"Estimated on-demand monthly price in USD. `None` when the instance\ntype is unknown or not in the price table."},"name":{"type":"string","description":"Node name"},"region":{"type":["string","null"],"description":"Region from `topology.kubernetes.io/region`"}}},"NodeInfoResponse":{"type":"object","required":["id","name","address","private_address","role","status","labels","capacity","created_at"],"properties":{"address":{"type":"string"},"architecture":{"type":["string","null"],"description":"Container platform this node runs (`linux/amd64`, `linux/arm64`).\n`None` until an agent that reports it has heartbeated."},"capacity":{"description":"Resource capacity/usage metrics from the latest heartbeat"},"created_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"labels":{},"last_heartbeat":{"type":["string","null"]},"name":{"type":"string"},"private_address":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"}}},"NodeListResponse":{"type":"object","required":["nodes","total"],"properties":{"nodes":{"type":"array","items":{"$ref":"#/components/schemas/NodeInfoResponse"}},"total":{"type":"integer","minimum":0}}},"NotificationPreferencesResponse":{"type":"object","required":["email_enabled","slack_enabled","batch_similar_notifications","minimum_severity","deployment_failures_enabled","build_errors_enabled","runtime_errors_enabled","error_threshold","error_time_window","ssl_expiration_enabled","ssl_days_before_expiration","domain_expiration_enabled","dns_changes_enabled","backup_failures_enabled","backup_successes_enabled","s3_connection_issues_enabled","retention_policy_violations_enabled","route_downtime_enabled","load_balancer_issues_enabled","weekly_digest_enabled","digest_send_day","digest_send_time","digest_sections"],"properties":{"backup_failures_enabled":{"type":"boolean"},"backup_successes_enabled":{"type":"boolean"},"batch_similar_notifications":{"type":"boolean"},"build_errors_enabled":{"type":"boolean"},"deployment_failures_enabled":{"type":"boolean"},"digest_sections":{"$ref":"#/components/schemas/DigestSections"},"digest_send_day":{"type":"string"},"digest_send_time":{"type":"string"},"dns_changes_enabled":{"type":"boolean"},"domain_expiration_enabled":{"type":"boolean"},"email_enabled":{"type":"boolean"},"error_threshold":{"type":"integer","format":"int32"},"error_time_window":{"type":"integer","format":"int32"},"load_balancer_issues_enabled":{"type":"boolean"},"minimum_severity":{"type":"string"},"retention_policy_violations_enabled":{"type":"boolean"},"route_downtime_enabled":{"type":"boolean"},"runtime_errors_enabled":{"type":"boolean"},"s3_connection_issues_enabled":{"type":"boolean"},"slack_enabled":{"type":"boolean"},"ssl_days_before_expiration":{"type":"integer","format":"int32"},"ssl_expiration_enabled":{"type":"boolean"},"weekly_digest_enabled":{"type":"boolean"}}},"NotificationProviderResponse":{"type":"object","required":["id","name","provider_type","config","enabled","created_at","updated_at"],"properties":{"config":{},"created_at":{"type":"integer","format":"int64"},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"ObservabilityCompressionSettings":{"type":"object","description":"TimescaleDB compression policy configuration for append-only observability\ntables. Values are expressed in hours so operators can choose sub-day\nwindows while keeping the API representation unambiguous.","properties":{"otel_spans_after_hours":{"type":"integer","format":"int32","description":"Compress OpenTelemetry span chunks after this many hours. Defaults to\n24 hours.","default":24,"example":24,"maximum":2160,"minimum":1},"proxy_logs_after_hours":{"type":"integer","format":"int32","description":"Compress proxy-log chunks after this many hours. Defaults to 24 hours.","default":24,"example":24,"maximum":720,"minimum":1}}},"ObservabilityEvent":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/RequestRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["request"]}}}]},{"allOf":[{"$ref":"#/components/schemas/SpanRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["span"]}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/RevenueRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["revenue"]}}}]}],"description":"Discriminated union of every row that can appear in the Observe list.\n\nSerializes to `{ \"type\": \"request\" | \"span\" | ... , ...rest }` so the UI\ncan switch on `event.type` without ambiguity.\n\n**No `Log` variant**: runtime stdout/stderr lines live on a dedicated\nLogs page rather than Observe. Logs are too high-volume to interleave\nwith business signals (requests, errors, revenue) without dominating\nthe timeline, and they have their own retention/storage constraints\n(TimescaleDB hypertable + chunked file/S3 store) that don't compose\nwith the merge service's per-kind LIMIT strategy."},"ObservabilityRetentionSettings":{"type":"object","description":"Retention policy configuration for raw observability tables. Values are in\ndays. The Settings API applies them to TimescaleDB; ClickHouse-backed proxy\nlogs and spans retain their storage-level per-row TTL behavior.","properties":{"otel_logs_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry log events for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"otel_metrics_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry metric points for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"otel_spans_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry spans (traces) for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"proxy_logs_days":{"type":"integer","format":"int32","description":"Retain proxy request logs for this many days.","default":30,"example":30,"maximum":3650,"minimum":1}}},"OidcProviderResponse":{"type":"object","required":["id","name","issuer_url","client_id","client_secret","scopes","jit_provisioning","enabled","template","group_claim","role_claim","default_role","trust_idp_email"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string","description":"Always masked — the secret is never returned after creation."},"default_role":{"type":"string"},"enabled":{"type":"boolean"},"group_claim":{"type":"string"},"id":{"type":"integer","format":"int32"},"issuer_url":{"type":"string"},"jit_provisioning":{"type":"boolean"},"name":{"type":"string"},"role_claim":{"type":"string"},"scopes":{"type":"string"},"template":{"type":"string"},"trust_idp_email":{"type":"boolean","description":"When true, the resolver skips the `email_verified` claim gate\nduring SSO login. Only safe for IdPs where an admin controls\nuser provisioning — see `oidc_providers::Model::trust_idp_email`."}}},"OidcProviderSummary":{"type":"object","required":["slug","name","template"],"properties":{"name":{"type":"string"},"slug":{"type":"string","description":"Stable opaque slug — use this as the path parameter when initiating\nOIDC login (`/auth/oidc/login/{slug}`). The integer database ID is\nintentionally omitted from this public endpoint to prevent provider\nenumeration."},"template":{"type":"string","description":"The template the provider was created from — e.g. `keycloak`,\n`okta`, `auth0`, `google`, `azure-ad`, or `generic`. Surfaced on\nthe public login endpoint so the unauthenticated login page can\nrender the right brand logo on the \"Sign in with X\" button.\nNever sensitive — the template name is part of the provider's\npublic identity, not configuration."}}},"OidcProviderUserResponse":{"type":"object","description":"A user that has logged in via a given OIDC provider. Used by the\nadmin \"Users for provider\" panel — the `oidc_subject` is the\nIdP-side identifier we matched on, useful when diagnosing why a\nuser can or can't log in.","required":["id","name","email","email_verified","mfa_enabled","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-15T14:30:00Z"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"oidc_subject":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time","example":"2024-01-15T14:30:00Z"}}},"OidcProvidersListResponse":{"type":"object","required":["providers"],"properties":{"providers":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderSummary"}}}},"OidcRoleMappingResponse":{"type":"object","required":["id","provider_id","priority","idp_group","role"],"properties":{"id":{"type":"integer","format":"int32"},"idp_group":{"type":"string"},"priority":{"type":"integer","format":"int32"},"provider_id":{"type":"integer","format":"int32"},"role":{"type":"string"}}},"OidcTestConnectionResponse":{"type":"object","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"OnDemandCertAttemptResponse":{"type":"object","description":"A single on-demand HTTP-01 issuance attempt from the append-only\n`on_demand_cert_attempts` audit log. Carries the full forensic detail for one\nattempt; the current cert state lives on the enclosing row's domain fields.\n\nContains no private-key or certificate material — only audit metadata — so it\nis safe to return without masking.","required":["id","hostname","trigger","outcome","created_at"],"properties":{"acme_request_sent":{"type":["boolean","null"],"description":"Did we reach the Let's Encrypt API?"},"acme_response_status":{"type":["string","null"],"description":"HTTP status or ACME error type returned by Let's Encrypt, when known."},"challenge_served":{"type":["boolean","null"],"description":"Did the proxy serve the `/.well-known/acme-challenge/` request?"},"created_at":{"type":"integer","format":"int64","description":"When the attempt was recorded (epoch millis)."},"duration_ms":{"type":["integer","null"],"format":"int32","description":"End-to-end issuance duration in milliseconds (0/None for skipped)."},"error_category":{"type":["string","null"],"description":"Coarse error category for UI labelling: `\"rate_limited\"`, `\"dns_failure\"`,\n`\"acme_order_expired\"`, `\"challenge_mismatch\"`, `\"timeout\"`, `\"internal\"`."},"error_chain":{"type":["string","null"],"description":"Full `Display` chain of the error (all `source()` levels), when failed."},"hostname":{"type":"string","description":"SNI hostname that triggered the attempt."},"id":{"type":"integer","format":"int32"},"outcome":{"type":"string","description":"Final outcome: `\"issued\"`, `\"failed\"`, `\"skipped_duplicate\"`,\n`\"skipped_gate\"`, `\"skipped_rate_limit\"`, or `\"skipped_no_route\"`."},"trigger":{"type":"string","description":"What triggered the attempt (always `\"tls_callback\"` today)."}}},"OnDemandCertRow":{"type":"object","description":"One row of the on-demand certificates list: the most-recent attempt for a\nhostname plus the current authoritative cert state from its `domains` row.","required":["hostname","attempt"],"properties":{"attempt":{"$ref":"#/components/schemas/OnDemandCertAttemptResponse","description":"The audit record for the attempt this row represents (newest first in\nthe list)."},"backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand negative-cache deadline (epoch millis), when in backoff."},"expiration_time":{"type":["integer","null"],"format":"int64","description":"Certificate expiration (epoch millis), when an active cert exists."},"hostname":{"type":"string","description":"SNI hostname."},"status":{"type":["string","null"],"description":"Current cert lifecycle status from the `domains` row, when one exists:\n`on_demand_pending`, `on_demand_issuing`, `active`, `on_demand_failed`,\netc. `None` when no `domains` row exists yet for this hostname."}}},"OnDemandTlsSettings":{"type":"object","description":"On-demand (lazy) HTTP-01 TLS issuance settings (ADR-018).\n\nWhen `enabled`, the proxy's `certificate_callback` triggers ACME HTTP-01\nissuance for allowlisted, STABLE hostnames (per-environment aliases and the\nconsole host) that have no active cert, rather than silently failing the\nhandshake. Ephemeral per-deployment hostnames are NEVER certed (ADR §2).\n\nOff by default — operators opt in explicitly, except QuickStart (`sslip.io`)\ninstalls where `temps setup` auto-enables it and derives `zone`.","properties":{"deployment_url_mode":{"type":"string","description":"How ephemeral per-deployment hostnames behave when they have no cert\n(they are NEVER certed — see ADR §2). One of:\n - `\"http\"` (default): serve plain HTTP on :80.\n - `\"redirect_to_env\"`: 308-redirect to the stable per-environment URL,\n which IS certed.","default":"http","example":"http"},"enabled":{"type":"boolean","description":"Master switch. When `false` (default) the proxy's on-demand cert gate\nrejects every SNI and no issuance is ever triggered.","default":false,"example":false},"hourly_cap":{"type":"integer","format":"int32","description":"Global cap on total on-demand issuances per hour across all hostnames\n(ADR §4 Layer 3). The operator's self-imposed safety net, separate from\nthe Let's Encrypt rate limit.","default":10,"example":10,"minimum":1},"max_concurrent":{"type":"integer","format":"int32","description":"Maximum number of ACME issuance flows allowed to run simultaneously\n(the concurrent-issuance semaphore, ADR §4 Layer 1). Min 1.","default":3,"example":3,"minimum":1},"zone":{"type":["string","null"],"description":"Zone suffix for the allowlist gate. A hostname passes the gate only if\nit is a direct subdomain of this zone (e.g. zone `1.2.3.4.sslip.io`\nadmits `myapp.1.2.3.4.sslip.io` but not `deep.sub.1.2.3.4.sslip.io`).\n`None` (default) means \"auto-derive from `external_url`\"; if no zone can\nbe derived the gate rejects all SNI, disabling the feature.","default":null,"example":"1.2.3.4.sslip.io"}}},"OpenAiError":{"type":"object","required":["message","type"],"properties":{"code":{"type":["string","null"]},"message":{"type":"string"},"type":{"type":"string"}}},"OpenAiErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/OpenAiError"}}},"OperatingSystemCount":{"type":"object","required":["operating_system","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"operating_system":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"OperationResultResponse":{"type":"object","required":["operation","success","message","executed_at"],"properties":{"data":{},"executed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"message":{"type":"string"},"operation":{"type":"string"},"success":{"type":"boolean"}}},"OperationResultsResponse":{"type":"object","required":["deployment_id","operations"],"properties":{"deployment_id":{"type":"string"},"operations":{"type":"array","items":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"OtelDashboardResponse":{"type":"object","required":["id","project_id","name","layout","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"id":{"type":"integer","format":"int32"},"layout":{"$ref":"#/components/schemas/DashboardLayout"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"}}},"OtelDashboardsResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OtelDashboardResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"OtelMetricAlertRuleResponse":{"type":"object","required":["id","project_id","name","metric_name","aggregation","detection_kind","detection_config","window_secs","for_duration_secs","severity","enabled","last_state","label_filters","group_by","dynamic_alerts","max_series","grouped_notification_threshold","last_dropped_series_count","series_states","created_at","updated_at"],"properties":{"aggregation":{"type":"string"},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"The typed detector definition (discriminated union keyed by `kind`)."},"detection_kind":{"type":"string","description":"Coarse detector discriminator: `static|anomaly|forecast|outlier|auto_watch`."},"dynamic_alerts":{"type":"boolean","description":"Whether per-series (\"dynamic\") alerting is enabled for this rule."},"enabled":{"type":"boolean"},"firing_series":{"type":"array","items":{"$ref":"#/components/schemas/FiringSeriesEntry"},"description":"Currently-firing series for a dynamic rule, snapshotted from the evaluator's\nin-memory firing map at read time. Empty for static/aggregate rules or when\nnothing is firing."},"for_duration_secs":{"type":"integer","format":"int32"},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys the rule breaks the metric down by. Empty = one aggregate stream."},"grouped_notification_threshold":{"type":"integer","format":"int32","description":"Notification-grouping threshold: when more than this many series fire in the\nsame tick, only the first gets chart/AI enrichment (1–1000)."},"id":{"type":"integer","format":"int32"},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters applied when evaluating this rule.\nEmpty = no filtering (matches all series)."},"last_dropped_series_count":{"type":"integer","format":"int32","description":"Number of series dropped by the cardinality cap on the latest dynamic tick\n(0 when nothing was dropped or for static/aggregate rules). Lets a UI warn\n\"N series were dropped this tick\" without reading server logs."},"last_evaluated_at":{"type":["string","null"],"example":"2025-10-12T12:15:47.609192Z"},"last_state":{"type":"string","description":"One of `ok|firing|unknown`."},"last_value":{"type":["number","null"],"format":"double"},"max_series":{"type":"integer","format":"int32","description":"Cardinality cap for dynamic alerting (1–100)."},"metric_name":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"series_states":{"type":"object","description":"Full per-series state snapshot persisted after the latest dynamic-rule tick,\nkeyed by the human-readable series label (`endpoint=/checkout`). Empty for\nstatic/aggregate rules. Unlike `firing_series` (a live in-memory snapshot),\nthis is decoded from the persisted `series_states` jsonb column, so an\nexternal consumer that only reads the rule row still sees per-series detail.","additionalProperties":{"$ref":"#/components/schemas/SeriesStateEntry"},"propertyNames":{"type":"string"}},"severity":{"type":"string"},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"window_secs":{"type":"integer","format":"int32"}}},"OtelMetricAlertsResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"OtelMetricLabelKeysResponse":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"}}}},"OtelMetricLabelValuesResponse":{"type":"object","required":["values"],"properties":{"values":{"type":"array","items":{"type":"string"}}}},"OtelMetricNamesResponse":{"type":"object","required":["names"],"properties":{"names":{"type":"array","items":{"type":"string"}}}},"OtelMetricsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/MetricBucket"}}}},"OutlierAlgorithm":{"type":"string","description":"Outlier detection algorithm.","enum":["dbscan","scaled_dbscan","mad","scaled_mad"]},"OutlierParams":{"type":"object","description":"Outlier (cross-series population) detector parameters (stub — not evaluated).","required":["peer_group_key"],"properties":{"algorithm":{"$ref":"#/components/schemas/OutlierAlgorithm"},"peer_group_key":{"type":"string","description":"Label key defining the peer population compared across series (e.g. `host`)."},"tolerance":{"type":"number","format":"double","description":"Sensitivity; higher tolerates larger spread before flagging."}}},"OverprovisioningAssessment":{"type":"object","description":"Requests-vs-capacity-vs-usage assessment","required":["verdict","explanation"],"properties":{"cpu_request_inflation_ratio":{"type":["number","null"],"format":"double","description":"Ratio of requested CPU to measured CPU usage (e.g. 40.0 = requests\nreserve 40× what the workloads actually use). `None` without metrics."},"cpu_requested_pct":{"type":["number","null"],"format":"double","description":"Requested CPU as % of cluster capacity"},"cpu_utilization_pct":{"type":["number","null"],"format":"double","description":"Measured CPU usage as % of cluster capacity (`None` without metrics)"},"explanation":{"type":"string","description":"Human-readable explanation of the verdict, e.g. \"Cluster capacity is\n8 vCPU but measured usage is 0.3 vCPU (3.7%) — severely overprovisioned\""},"memory_request_inflation_ratio":{"type":["number","null"],"format":"double","description":"Ratio of requested memory to measured memory usage"},"memory_requested_pct":{"type":["number","null"],"format":"double","description":"Requested memory as % of cluster capacity"},"memory_utilization_pct":{"type":["number","null"],"format":"double","description":"Measured memory usage as % of cluster capacity (`None` without metrics)"},"verdict":{"$ref":"#/components/schemas/OverprovisioningVerdict","description":"Overall verdict"}}},"OverprovisioningVerdict":{"type":"string","description":"Overall overprovisioning verdict","enum":["severe","moderate","reasonable","unknown"]},"PageActivityBucket":{"type":"object","description":"Time bucket data point for page activity graph","required":["timestamp","visitors","page_views","avg_time_seconds"],"properties":{"avg_time_seconds":{"type":"number","format":"double","description":"Average time on page in seconds"},"page_views":{"type":"integer","format":"int64","description":"Number of page views in this bucket"},"timestamp":{"type":"string","description":"Timestamp for this bucket (ISO 8601)"},"visitors":{"type":"integer","format":"int64","description":"Number of unique visitors in this bucket"}}},"PageCountryStats":{"type":"object","description":"Geographic distribution of visitors for a page","required":["country","visitors","page_views","percentage"],"properties":{"country":{"type":"string","description":"Country name"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"page_views":{"type":"integer","format":"int64","description":"Number of page views from this country"},"percentage":{"type":"number","format":"double","description":"Percentage of total visitors"},"visitors":{"type":"integer","format":"int64","description":"Number of unique visitors from this country"}}},"PageFlowEntry":{"type":"object","description":"A single page with its entry/exit/bounce statistics","required":["page_path","entry_count","exit_count","bounce_count","total_views","entry_rate","exit_rate","bounce_rate"],"properties":{"avg_time_on_page":{"type":["number","null"],"format":"double","description":"Average time spent on this page in seconds"},"bounce_count":{"type":"integer","format":"int64","description":"Number of times visitors bounced on this page"},"bounce_rate":{"type":"number","format":"double","description":"Bounce rate: bounce_count / entry_count (only meaningful for entry pages)"},"entry_count":{"type":"integer","format":"int64","description":"Number of times this page was the entry page of a session"},"entry_rate":{"type":"number","format":"double","description":"Entry rate: entry_count / total_views"},"exit_count":{"type":"integer","format":"int64","description":"Number of times this page was the exit page of a session"},"exit_rate":{"type":"number","format":"double","description":"Exit rate: exit_count / total_views"},"page_path":{"type":"string","description":"The page path (e.g. \"/pricing\", \"/docs/getting-started\")"},"total_views":{"type":"integer","format":"int64","description":"Total page views for this page"}}},"PageFlowQuery":{"type":"object","description":"Query parameters for page flow analytics","required":["project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of entry/exit pages to return (default: 20)"},"min_views_for_dropoff":{"type":["integer","null"],"format":"int32","description":"Minimum views for drop-off analysis (default: 5)"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"},"transitions_limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of transitions to return (default: 50)"}}},"PageFlowResponse":{"type":"object","description":"Complete page flow analytics response","required":["top_entry_pages","top_exit_pages","drop_off_points","transitions","total_pages","total_sessions"],"properties":{"drop_off_points":{"type":"array","items":{"$ref":"#/components/schemas/DropOffPoint"},"description":"Top drop-off points (highest exit rates with meaningful traffic)"},"top_entry_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageFlowEntry"},"description":"Top entry pages (where visitors land), sorted by entry_count DESC"},"top_exit_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageFlowEntry"},"description":"Top exit pages (where visitors leave), sorted by exit_count DESC"},"total_pages":{"type":"integer","format":"int64","description":"Total unique pages seen in the period"},"total_sessions":{"type":"integer","format":"int64","description":"Total sessions in the period"},"transitions":{"type":"array","items":{"$ref":"#/components/schemas/PageTransition"},"description":"Page-to-page transitions (most common navigation paths)"}}},"PageHourlySessionsQuery":{"type":"object","description":"Query parameters for page hourly sessions endpoint","required":["page_path","project_id","start_time","end_time"],"properties":{"bucket_interval":{"type":["string","null"]},"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"PageHourlySessionsResponse":{"type":"object","required":["page_path","hourly_data","total_sessions","hours"],"properties":{"hourly_data":{"type":"array","items":{"$ref":"#/components/schemas/HourlyPageSessions"}},"hours":{"type":"integer","format":"int32"},"page_path":{"type":"string"},"total_sessions":{"type":"integer","format":"int64"}}},"PagePathDetailQuery":{"type":"object","description":"Query parameters for page path detail analytics","required":["page_path","project_id","start_date","end_date"],"properties":{"bucket_interval":{"type":["string","null"],"description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string","description":"The specific page path to get details for (URL-encoded)"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PagePathDetailResponse":{"type":"object","description":"Detailed analytics response for a specific page path","required":["page_path","unique_visitors","total_page_views","avg_time_on_page","bounce_rate","entry_rate","exit_rate","activity_over_time","countries","referrers","bucket_interval"],"properties":{"activity_over_time":{"type":"array","items":{"$ref":"#/components/schemas/PageActivityBucket"},"description":"Time series data for activity graph"},"avg_time_on_page":{"type":"number","format":"double","description":"Average time on page in seconds"},"bounce_rate":{"type":"number","format":"double","description":"Bounce rate percentage (0-100)"},"bucket_interval":{"type":"string","description":"Bucket interval used for time series ('hour', 'day', etc.)"},"countries":{"type":"array","items":{"$ref":"#/components/schemas/PageCountryStats"},"description":"Geographic distribution of visitors"},"entry_rate":{"type":"number","format":"double","description":"Entry rate - percentage of sessions that started on this page"},"exit_rate":{"type":"number","format":"double","description":"Exit rate - percentage of sessions that ended on this page"},"page_path":{"type":"string","description":"The page path being analyzed"},"referrers":{"type":"array","items":{"$ref":"#/components/schemas/PageReferrerStats"},"description":"Top referrers to this page"},"total_page_views":{"type":"integer","format":"int64","description":"Total page views in the date range"},"unique_visitors":{"type":"integer","format":"int64","description":"Total unique visitors to this page in the date range"}}},"PagePathInfo":{"type":"object","required":["page_path","session_count","page_view_count","first_seen","last_seen"],"properties":{"avg_time_seconds":{"type":["number","null"],"format":"double"},"first_seen":{"type":"string"},"last_seen":{"type":"string"},"page_path":{"type":"string"},"page_view_count":{"type":"integer","format":"int64"},"session_count":{"type":"integer","format":"int64"}}},"PagePathSparkline":{"type":"object","required":["page_path","points"],"properties":{"page_path":{"type":"string"},"points":{"type":"array","items":{"$ref":"#/components/schemas/PagePathSparklinePoint"}}}},"PagePathSparklinePoint":{"type":"object","required":["timestamp","session_count"],"properties":{"session_count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"PagePathVisitorsQuery":{"type":"object","description":"Query parameters for page path visitors","required":["page_path","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"page_path":{"type":"string","description":"The specific page path to get visitors for"},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 50, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PagePathVisitorsResponse":{"type":"object","description":"Response for page path visitors endpoint","required":["page_path","total_count","page","per_page","sessions"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"page_path":{"type":"string","description":"The page path"},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/PageVisitorSession"},"description":"Individual visitor sessions"},"total_count":{"type":"integer","format":"int64","description":"Total number of visitor sessions matching the query"}}},"PagePathsQuery":{"type":"object","required":["project_id"],"properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":["string","null"],"format":"date-time"}}},"PagePathsResponse":{"type":"object","required":["page_paths","total_count"],"properties":{"page_paths":{"type":"array","items":{"$ref":"#/components/schemas/PagePathInfo"}},"total_count":{"type":"integer","minimum":0}}},"PagePathsSparklineQuery":{"type":"object","description":"Query parameters for batch page paths sparkline endpoint","required":["project_id","start_time","end_time","page_paths"],"properties":{"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_paths":{"type":"string","description":"Comma-separated list of page paths"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"PagePathsSparklineResponse":{"type":"object","required":["sparklines"],"properties":{"sparklines":{"type":"array","items":{"$ref":"#/components/schemas/PagePathSparkline"}}}},"PageReferrerStats":{"type":"object","description":"Referrer source for the page","required":["referrer","visits","percentage"],"properties":{"percentage":{"type":"number","format":"double","description":"Percentage of total visits"},"referrer":{"type":"string","description":"Referrer URL or domain"},"visits":{"type":"integer","format":"int64","description":"Number of visits from this referrer"}}},"PageSessionComparison":{"type":"object","required":["page_path","date","session_count","event_count","avg_duration_seconds"],"properties":{"avg_duration_seconds":{"type":"number","format":"double"},"date":{"type":"string"},"event_count":{"type":"integer","format":"int64"},"page_path":{"type":"string"},"session_count":{"type":"integer","format":"int64"}}},"PageSessionStats":{"type":"object","required":["page_path","total_sessions","avg_time_seconds","min_time_seconds","max_time_seconds","total_page_views","avg_page_views_per_session"],"properties":{"avg_page_views_per_session":{"type":"number","format":"double"},"avg_time_seconds":{"type":"number","format":"double"},"max_time_seconds":{"type":"number","format":"double"},"min_time_seconds":{"type":"number","format":"double"},"page_path":{"type":"string"},"total_page_views":{"type":"integer","format":"int64"},"total_sessions":{"type":"integer","format":"int64"}}},"PageSessionStatsQuery":{"type":"object","required":["page_path","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PageTransition":{"type":"object","description":"A page-to-page transition with count","required":["from_page","to_page","transition_count","percentage"],"properties":{"from_page":{"type":"string","description":"The source page path"},"percentage":{"type":"number","format":"double","description":"Percentage of transitions from the source page that go to this destination"},"to_page":{"type":"string","description":"The destination page path"},"transition_count":{"type":"integer","format":"int64","description":"Number of times this transition occurred"}}},"PageVisit":{"type":"object","required":["path","visits"],"properties":{"path":{"type":"string"},"visits":{"type":"integer","format":"int64"}}},"PageVisitorSession":{"type":"object","description":"Individual visitor session that viewed a specific page","required":["visitor_id","visitor_uuid","viewed_at","is_entry","is_exit","is_bounce"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"Visitor's city"},"country":{"type":["string","null"],"description":"Visitor's country"},"country_code":{"type":["string","null"],"description":"Visitor's country code"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"is_bounce":{"type":"boolean","description":"Whether this was a bounce"},"is_entry":{"type":"boolean","description":"Whether this was the entry page for the session"},"is_exit":{"type":"boolean","description":"Whether this was the exit page for the session"},"operating_system":{"type":["string","null"],"description":"Operating system"},"referrer":{"type":["string","null"],"description":"Referrer URL"},"session_id":{"type":["string","null"],"description":"Session ID"},"session_page_number":{"type":["integer","null"],"format":"int32","description":"Page number in session flow"},"time_on_page":{"type":["integer","null"],"format":"int32","description":"Time spent on this page in seconds"},"viewed_at":{"type":"string","format":"date-time","description":"When the page was viewed"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor numeric ID"},"visitor_uuid":{"type":"string","description":"Visitor UUID"}}},"PagesComparisonResponse":{"type":"object","required":["comparisons","page_paths"],"properties":{"comparisons":{"type":"array","items":{"$ref":"#/components/schemas/PageSessionComparison"}},"page_paths":{"type":"array","items":{"type":"string"}}}},"PaginatedEmailsResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedEntitiesResponse":{"type":"object","required":["entities","count","limit","has_more"],"properties":{"count":{"type":"integer","description":"Number of entities returned","minimum":0},"entities":{"type":"array","items":{"$ref":"#/components/schemas/EntityResponse"},"description":"List of entities"},"has_more":{"type":"boolean","description":"Whether there are more entities available"},"limit":{"type":"integer","description":"Limit used for this request","minimum":0},"next_token":{"type":["string","null"],"description":"Continuation token for next page (S3, etc.)"},"total":{"type":["integer","null"],"description":"Total number of entities (if available)","minimum":0}}},"PaginatedErrorEventsResponse":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ErrorEventResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationMeta"}}},"PaginatedErrorGroupsResponse":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ErrorGroupResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationMeta"}}},"PaginatedEventsResponse":{"type":"object","required":["events","total","page","page_size"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/TrackingEventResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedExternalImagesResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExternalImageResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedProjectList":{"type":"object","required":["projects","total","page","per_page"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"projects":{"type":"array","items":{"$ref":"#/components/schemas/ProjectResponse"}},"total":{"type":"integer","format":"int64"}}},"PaginatedStaticBundlesResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StaticBundleResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"Pagination":{"type":"object","description":"SDK pagination cursor. We use opaque page numbers internally but\nexpose `count`/`next`/`prev` the way `@vercel/sandbox` expects.","required":["count"],"properties":{"count":{"type":"integer","format":"int64","minimum":0},"next":{"type":["integer","null"],"format":"int64","minimum":0},"prev":{"type":["integer","null"],"format":"int64","minimum":0}}},"PaginationMeta":{"type":"object","required":["page","page_size","total_count","total_pages"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total_count":{"type":"integer","format":"int64","minimum":0},"total_pages":{"type":"integer","format":"int64","minimum":0}}},"PaginationParams":{"type":"object","properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"}}},"PasswordProtectionConfig":{"type":"object","description":"Password protection configuration\n\nWhen enabled, the proxy shows an HTML password form before allowing access.\nAfter the user enters the correct password, an HMAC-signed cookie is set\nso subsequent requests pass through without re-entering the password.","required":["enabled","passwordHash"],"properties":{"enabled":{"type":"boolean","description":"Whether password protection is enabled"},"passwordHash":{"type":"string","description":"The bcrypt-hashed password (never stored or returned in plaintext)"}}},"PatchSettingsRequest":{"type":"object","properties":{"auto_upgrade":{"type":["boolean","null"]},"host_port":{"type":["integer","null"],"format":"int32","minimum":0},"image":{"type":["string","null"]}}},"PathVisitors":{"type":"object","required":["name","visitors","percentage"],"properties":{"name":{"type":"string"},"percentage":{"type":"number","format":"double"},"visitors":{"type":"integer","format":"int64"}}},"PathVisitorsAnalyticsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PathVisitorsResponse":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PathVisitors"}}}},"PeerEntry":{"type":"object","description":"Wire-format peer entry. Matches `temps_network::config::Peer` but\nuses strings on the wire to keep the API stable across underlying\ntype evolution.","required":["node_id","compute_cidr","underlay_address"],"properties":{"compute_cidr":{"type":"string","description":"Per-node CIDR (e.g. `\"172.20.5.0/24\"`)."},"node_id":{"type":"string","description":"Stable v5 UUID derived from the database node id. Workers use\nthis as the kernel-layer identifier when calling\n`NetworkManager::reconcile_peers`."},"underlay_address":{"type":"string","description":"Address the local node should use to reach this peer over the\nunderlay (private VPC IP for same-DC, public IP for cross-DC)."}}},"PeerListResponse":{"type":"object","description":"Response body for `GET /internal/nodes/{node_id}/network/peers`.","required":["peers","cluster_dns_enabled"],"properties":{"alloc":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AllocEntry","description":"Caller's own allocation, or `null` if multi-host networking has\nnot been enabled for this node yet."}]},"cluster_dns_enabled":{"type":"boolean","description":"Whether the cluster-DNS resolver is enabled on this control plane\n(`AppSettings.cluster_dns.enabled`). Workers should start their\nper-node resolver and write `overlay_bridge_address` only when this\nis `true`. Always serialized (never `skip_serializing_if`) so older\nand newer version skew degrades to the safe default of `false`."},"peers":{"type":"array","items":{"$ref":"#/components/schemas/PeerEntry"},"description":"All other nodes with a `compute_cidr` set, excluding the caller."}}},"PendingActionResponse":{"type":"object","description":"A proposed AI write action awaiting human confirmation.","required":["public_id","operation_id","method","summary","status","step_index","params","created_at"],"properties":{"confirmed_at":{"type":["string","null"]},"created_at":{"type":"string"},"error":{"type":["string","null"]},"executed_at":{"type":["string","null"]},"method":{"type":"string"},"operation_id":{"type":"string"},"params":{"description":"The flat params to be replayed at execute time (shown pre-execution for review)."},"plan_public_id":{"type":["string","null"],"description":"Set when this action is one step of a multi-step plan (chained actions);\nall steps of the plan share this id. Absent for standalone single actions."},"public_id":{"type":"string"},"required_permission":{"type":["string","null"]},"result":{},"status":{"type":"string"},"step_index":{"type":"integer","format":"int32","description":"0-based order of this step within its plan (0 for standalone actions)."},"summary":{"type":"string"}}},"PerformanceMetricsQuery":{"allOf":[{"$ref":"#/components/schemas/SpeedSegmentFilters","description":"Segment filters (filter_path, filter_country, filter_region,\nfilter_city, filter_browser, filter_operating_system) — flattened so\neach remains a top-level query string param."},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"],"description":"Device type filter: \"desktop\" or \"mobile\""},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"include_bots":{"type":["boolean","null"],"description":"Include crawler/datacenter (bot) samples. Defaults to false — bots\nare excluded from the read view but always stored at ingest."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"PerformanceMetricsResponse":{"type":"object","properties":{"cls":{"type":["number","null"],"format":"float"},"cls_p75":{"type":["number","null"],"format":"float"},"cls_p90":{"type":["number","null"],"format":"float"},"cls_p95":{"type":["number","null"],"format":"float"},"cls_p99":{"type":["number","null"],"format":"float"},"fcp":{"type":["number","null"],"format":"float"},"fcp_p75":{"type":["number","null"],"format":"float"},"fcp_p90":{"type":["number","null"],"format":"float"},"fcp_p95":{"type":["number","null"],"format":"float"},"fcp_p99":{"type":["number","null"],"format":"float"},"fid":{"type":["number","null"],"format":"float"},"fid_p75":{"type":["number","null"],"format":"float"},"fid_p90":{"type":["number","null"],"format":"float"},"fid_p95":{"type":["number","null"],"format":"float"},"fid_p99":{"type":["number","null"],"format":"float"},"inp":{"type":["number","null"],"format":"float"},"inp_p75":{"type":["number","null"],"format":"float"},"inp_p90":{"type":["number","null"],"format":"float"},"inp_p95":{"type":["number","null"],"format":"float"},"inp_p99":{"type":["number","null"],"format":"float"},"lcp":{"type":["number","null"],"format":"float"},"lcp_p75":{"type":["number","null"],"format":"float"},"lcp_p90":{"type":["number","null"],"format":"float"},"lcp_p95":{"type":["number","null"],"format":"float"},"lcp_p99":{"type":["number","null"],"format":"float"},"ttfb":{"type":["number","null"],"format":"float"},"ttfb_p75":{"type":["number","null"],"format":"float"},"ttfb_p90":{"type":["number","null"],"format":"float"},"ttfb_p95":{"type":["number","null"],"format":"float"},"ttfb_p99":{"type":["number","null"],"format":"float"}}},"PermissionInfo":{"type":"object","description":"Information about a single permission","required":["name","description","category"],"properties":{"category":{"type":"string","description":"Category of the permission (e.g., \"Projects\", \"Deployments\")"},"description":{"type":"string","description":"Human-readable description of the permission"},"name":{"type":"string","description":"The permission identifier (e.g., \"projects:read\")"}}},"PgUpgradeLogResponse":{"type":"object","required":["log_id","content"],"properties":{"content":{"type":"string"},"log_id":{"type":"string"}}},"PgUpgradeResponse":{"type":"object","required":["id","service_id","from_version","to_version","from_image","to_image","status","phase","log_id","attempt","created_at"],"properties":{"attempt":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"finished_at":{"type":["string","null"]},"from_image":{"type":"string"},"from_version":{"type":"string"},"id":{"type":"integer","format":"int32"},"log_id":{"type":"string"},"phase":{"type":"string"},"pre_upgrade_backup_id":{"type":["integer","null"],"format":"int32"},"rollback_volume_name":{"type":["string","null"]},"service_id":{"type":"integer","format":"int32"},"started_at":{"type":["string","null"]},"status":{"type":"string"},"to_image":{"type":"string"},"to_version":{"type":"string"}}},"PipelineStats":{"type":"object","description":"Internal pipeline statistics for self-observability.","required":["metrics_received","metrics_stored","metrics_dropped","spans_received","spans_stored","spans_dropped","logs_received","logs_stored_db","logs_stored_s3","logs_dropped","ingest_errors"],"properties":{"ingest_errors":{"type":"integer","format":"int64","minimum":0},"logs_dropped":{"type":"integer","format":"int64","minimum":0},"logs_received":{"type":"integer","format":"int64","minimum":0},"logs_stored_db":{"type":"integer","format":"int64","minimum":0},"logs_stored_s3":{"type":"integer","format":"int64","minimum":0},"metrics_dropped":{"type":"integer","format":"int64","minimum":0},"metrics_received":{"type":"integer","format":"int64","minimum":0},"metrics_stored":{"type":"integer","format":"int64","minimum":0},"spans_dropped":{"type":"integer","format":"int64","minimum":0},"spans_received":{"type":"integer","format":"int64","minimum":0},"spans_stored":{"type":"integer","format":"int64","minimum":0}}},"PipelineStatsResponse":{"type":"object","required":["stats"],"properties":{"stats":{"$ref":"#/components/schemas/PipelineStats"}}},"PlanComplexity":{"type":"string","description":"Plan complexity indicator","enum":["low","medium","high"]},"PlanMetadata":{"type":"object","description":"Plan metadata","required":["generated_at","generator_version","complexity","warnings"],"properties":{"complexity":{"$ref":"#/components/schemas/PlanComplexity","description":"Estimated complexity (low, medium, high)"},"generated_at":{"type":"string","format":"date-time","description":"When the plan was generated"},"generator_version":{"type":"string","description":"Generator (importer) version"},"warnings":{"type":"array","items":{"type":"string"},"description":"Warnings detected during planning"}}},"PlanSourceBackup":{"type":"object","required":["location","location_was_resolved","format"],"properties":{"created_at":{"type":["string","null"]},"format":{"type":"string","description":"\"walg\", \"pg_dump\", \"unknown\"."},"id":{"type":["integer","null"],"format":"int32","description":"DB id, absent for orphan (S3-scan) backups."},"location":{"type":"string","description":"Resolved S3 location the orchestrator will actually use."},"location_was_resolved":{"type":"boolean","description":"True when the original row's `s3_location` was empty and we resolved\na location by probing S3. The UI shows this as a warning."},"origin_service_name":{"type":["string","null"],"description":"Service that originally produced the backup, if known."},"size_bytes":{"type":["integer","null"],"format":"int64"}}},"PlanTarget":{"type":"object","required":["id","name","container"],"properties":{"container":{"type":"string","description":"Expected Docker container name."},"id":{"type":"integer","format":"int32"},"name":{"type":"string"}}},"PlatformInfo":{"type":"object","description":"Platform compatibility information","required":["os_type","architecture","platforms"],"properties":{"architecture":{"type":"string","description":"System architecture (e.g., \"x86_64\", \"aarch64\")"},"os_type":{"type":"string","description":"Operating system type (e.g., \"linux\", \"windows\", \"darwin\")"},"platforms":{"type":"array","items":{"type":"string"},"description":"List of supported platforms in \"os/arch\" format (e.g., [\"linux/amd64\"])"}}},"PluginManifest":{"type":"object","description":"The complete plugin manifest — the handshake contract.","required":["name","version"],"properties":{"description":{"type":["string","null"],"description":"Short description of what the plugin does"},"display_name":{"type":["string","null"],"description":"Human-readable display name"},"events":{"type":"array","items":{"type":"string"},"description":"Platform event types the plugin subscribes to.\n\nWhen specified, Temps will POST matching events to the plugin's\n`/_events` endpoint. Uses dot-notation event names matching the\nwebhook event types (e.g., \"deployment.succeeded\", \"project.created\").\n\nAvailable events:\n- `deployment.created`, `deployment.succeeded`, `deployment.failed`,\n `deployment.cancelled`, `deployment.ready`\n- `project.created`, `project.deleted`\n- `domain.created`, `domain.provisioned`"},"health_path":{"type":"string","description":"Health check endpoint path (relative to plugin root)"},"name":{"type":"string","description":"Unique plugin identifier (kebab-case, e.g., \"backup-manager\")"},"nav":{"type":"array","items":{"$ref":"#/components/schemas/NavEntry"},"description":"Navigation entries for the UI sidebar"},"requires_db":{"type":"boolean","description":"Whether the plugin needs database access"},"ui":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UiManifest","description":"UI bundle manifest (if the plugin has a UI)"}]},"version":{"type":"string","description":"SemVer version string"}}},"PortMapping":{"type":"object","description":"Port mapping","required":["container_port","protocol","is_primary"],"properties":{"container_port":{"type":"integer","format":"int32","description":"Container port","minimum":0},"host_port":{"type":["integer","null"],"format":"int32","description":"Host port (optional - can be assigned dynamically)","minimum":0},"is_primary":{"type":"boolean","description":"Whether this is the primary HTTP port"},"protocol":{"$ref":"#/components/schemas/Protocol","description":"Protocol (tcp, udp)"}}},"PostgresWalHealth":{"type":"object","required":["probed_at","pg_wal_bytes","max_wal_size_bytes","archive_mode","archive_backlog","stale_slots","oldest_wal_age_secs","warnings"],"properties":{"archive_backlog":{"type":"integer","format":"int64","description":"Number of `archive_status/*.ready` files — un-shipped WAL segments."},"archive_command":{"type":["string","null"],"description":"The literal `archive_command` setting. May be empty or `/bin/true`\nwhen archiving is effectively disabled despite `archive_mode = on`."},"archive_mode":{"$ref":"#/components/schemas/ArchiveMode"},"archiver_failed_count":{"type":["integer","null"],"format":"int64"},"archiver_last_failed_at":{"type":["string","null"],"format":"date-time"},"max_wal_size_bytes":{"type":"integer","format":"int64","description":"`max_wal_size` setting in bytes (parsed from `pg_settings`)."},"oldest_wal_age_secs":{"type":"integer","format":"int64","description":"Age of the oldest WAL file in `pg_wal/` (seconds)."},"pg_wal_bytes":{"type":"integer","format":"int64","description":"Total size of files under `pg_wal/`, from `pg_ls_waldir()`."},"probed_at":{"type":"string","format":"date-time","description":"When the snapshot was taken."},"stale_slots":{"type":"array","items":{"$ref":"#/components/schemas/StaleSlot"}},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/WalWarning"},"description":"Computed warnings, ordered by severity (critical first)."}}},"PresetConfigSchema":{"oneOf":[{"$ref":"#/components/schemas/DockerfilePresetConfig","description":"Configuration for Dockerfile preset"},{"$ref":"#/components/schemas/DockerComposePresetConfig","description":"Configuration for Docker Compose"},{"$ref":"#/components/schemas/NixpacksPresetConfig","description":"Configuration for Nixpacks provider selection and inline build plan"},{"$ref":"#/components/schemas/StaticPresetConfig","description":"Configuration for static site presets (Vite, Next.js, etc.)"}],"description":"Union type for preset configurations\nUse the appropriate configuration type based on your preset"},"PresetInfo":{"type":"object","description":"Detected preset information","required":["path","preset","preset_label","project_type"],"properties":{"compose_files":{"type":["array","null"],"items":{"type":"string"},"description":"Compose file paths found in the repository (only for docker-compose preset)"},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Default exposed port for this preset"},"icon_url":{"type":["string","null"],"description":"Icon URL for this preset"},"path":{"type":"string","description":"Path where preset was detected (empty for root)"},"preset":{"type":"string","description":"Preset slug (e.g., \"nextjs\", \"fastapi\")"},"preset_label":{"type":"string","description":"Human-readable preset label"},"project_type":{"type":"string","description":"Project type (e.g., \"frontend\", \"backend\", \"fullstack\")"}}},"PresetResponse":{"type":"object","required":["slug","label","icon_url","project_type","description"],"properties":{"default_port":{"type":["integer","null"],"format":"int32","description":"Default port the application listens on (None for static sites)","example":3000,"minimum":0},"description":{"type":"string","description":"Description of what this preset does"},"icon_url":{"type":"string","description":"Icon URL for the preset"},"label":{"type":"string","description":"Display name/label for the preset"},"project_type":{"type":"string","description":"Project type (server or static)"},"slug":{"type":"string","description":"Unique identifier slug for the preset"}}},"PreviewGatewaySettings":{"type":"object","description":"Workspace preview gateway settings.\n\nThe preview gateway is a single shared Docker container that lives on the\n`temps-sandbox-net` network and routes requests to workspace sandbox dev\nservers based on the `Host` header (`ws--.`).\n`temps serve` reconciles this container on startup; these settings let an\noperator override the image, host port, and auto-upgrade behavior.","properties":{"auto_upgrade":{"type":"boolean","description":"When true (default), the supervisor will pull and apply the image\npinned in the Temps binary on every startup. When false, the\ncurrently-running image is left alone — operators upgrade manually\nfrom the settings UI.","default":true,"example":true},"host_port":{"type":"integer","format":"int32","description":"Host port to publish the gateway on (always bound to 127.0.0.1).\nPingora forwards `ws-*` traffic to this port after authenticating.","default":8090,"example":8090,"minimum":0},"image":{"type":"string","description":"Docker image reference for the gateway. Pinned per Temps release.\nOperators can override this to test a custom build.","default":"ghcr.io/gotempsh/temps-preview-gateway:latest","example":"ghcr.io/gotempsh/temps-preview-gateway:latest"},"shared_secret":{"type":"string","description":"Shared secret the host-side Pingora sends on every forwarded preview\nrequest via `X-Temps-Preview-Token`; the gateway rejects requests\nwithout it. Auto-generated on first boot, persisted in DB so the\nsecret is stable across `temps serve` restarts regardless of cwd,\n`TEMPS_DATA_DIR`, or data-dir changes. MUST be masked (`***`) in any\nAPI response — never expose it over HTTP.","default":"","example":""}}},"PreviewGatewaySettingsMasked":{"type":"object","description":"Preview gateway settings with `shared_secret` elided.","required":["image","host_port","auto_upgrade","shared_secret_set"],"properties":{"auto_upgrade":{"type":"boolean"},"host_port":{"type":"integer","format":"int32","minimum":0},"image":{"type":"string"},"shared_secret_set":{"type":"boolean"}}},"PreviewGatewaySettingsResponse":{"type":"object","required":["image","host_port","auto_upgrade","default_image","default_host_port"],"properties":{"auto_upgrade":{"type":"boolean"},"default_host_port":{"type":"integer","format":"int32","description":"The compile-time default host port.","minimum":0},"default_image":{"type":"string","description":"The compile-time default image — exposed so the UI can offer a\n\"Reset to default\" link without round-tripping."},"host_port":{"type":"integer","format":"int32","minimum":0},"image":{"type":"string"}}},"PricingResponse":{"type":"object","required":["models"],"properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/ModelPricing"}}}},"ProblemDetails":{"type":"object","description":"Representation of a Problem error to return to the client.\nFollows RFC 7807 - Problem Details for HTTP APIs","required":["title","extensions"],"properties":{"detail":{"type":["string","null"],"description":"A human-readable explanation specific to this occurrence of the problem","example":"The server encountered an unexpected condition"},"extensions":{"type":"object","description":"Additional properties of the problem","additionalProperties":true},"instance":{"type":["string","null"],"description":"A URI reference that identifies the specific occurrence of the problem","example":"/account/12345/msgs/abc"},"title":{"type":"string","description":"A short, human-readable summary of the problem type","example":"Internal Server Error"},"type":{"type":["string","null"],"description":"A URI reference that identifies the problem type","example":"https://example.com/probs/out-of-memory"}},"example":{"type":"https://example.com/probs/out-of-memory","title":"Internal Server Error","detail":"The server encountered an unexpected condition","instance":"/account/12345/msgs/abc","additional_info":"Custom field with additional details"}},"ProjectConfiguration":{"type":"object","description":"Project-level configuration","required":["name","slug","project_type","is_web_app"],"properties":{"is_web_app":{"type":"boolean","description":"Whether this is a web application"},"name":{"type":"string","description":"Proposed project name"},"project_type":{"$ref":"#/components/schemas/ProjectType","description":"Project type"},"slug":{"type":"string","description":"Proposed slug (URL-safe identifier)"}}},"ProjectDSNResponse":{"type":"object","required":["id","project_id","name","public_key","dsn","created_at","is_active","event_count"],"properties":{"created_at":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"dsn":{"type":"string"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_count":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"public_key":{"type":"string"}}},"ProjectDashboardAnalytics":{"type":"object","description":"Analytics data for a single project in the dashboard batch response","required":["project_id","unique_visitors","previous_unique_visitors","hourly_visits"],"properties":{"hourly_visits":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"},"description":"Hourly sparkline data points"},"previous_unique_visitors":{"type":"integer","format":"int64","description":"Unique visitor count in the previous period (same duration, shifted back)"},"project_id":{"type":"integer","format":"int32"},"trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change from previous period (positive = growth, negative = decline)\nNull when previous period had zero visitors (no baseline to compare)"},"unique_visitors":{"type":"integer","format":"int64","description":"Unique visitor count in the current time range"}}},"ProjectHealthSummary":{"type":"object","description":"Health summary for a single project (last 1 hour)","required":["project_id","total_requests","total_errors","avg_response_time_ms","error_rate","status"],"properties":{"avg_response_time_ms":{"type":"number","format":"double","description":"Average response time in ms"},"error_rate":{"type":"number","format":"double","description":"Error rate as a percentage (0-100)"},"project_id":{"type":"integer","format":"int32"},"status":{"type":"string","description":"Health status: \"healthy\", \"degraded\", \"down\", \"unknown\""},"total_errors":{"type":"integer","format":"int64","description":"Total server errors (status >= 500) in the period"},"total_requests":{"type":"integer","format":"int64","description":"Total requests in the period"}}},"ProjectInfo":{"type":"object","required":["id","slug","created_at"],"properties":{"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"id":{"type":"integer","format":"int32"},"slug":{"type":"string"}}},"ProjectMonitorHealth":{"type":"object","description":"Health summary for a single project based on its production monitors","required":["project_id","status"],"properties":{"project_id":{"type":"integer","format":"int32"},"status":{"type":"string","description":"Overall status: \"operational\", \"degraded\", \"down\", or \"no_monitors\""}}},"ProjectPresetResponse":{"type":"object","required":["path","preset","presetLabel","projectType"],"properties":{"composeFiles":{"type":["array","null"],"items":{"type":"string"},"description":"Compose file paths found in the repository (only for docker-compose preset)"},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Default exposed port for this preset (e.g., 3000 for Next.js, 8000 for FastAPI)"},"iconUrl":{"type":["string","null"],"description":"Icon URL for the preset"},"path":{"type":"string"},"preset":{"type":"string"},"presetLabel":{"type":"string"},"projectType":{"type":"string","description":"Project type category (e.g., \"frontend\", \"backend\", \"fullstack\")"}}},"ProjectQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"ProjectRef":{"type":"object","description":"A lightweight project descriptor included in `UnifiedTrace`.","required":["project_id","project_name","project_slug"],"properties":{"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link a span back into its owning project's trace view."}}},"ProjectResponse":{"type":"object","required":["id","slug","name","directory","main_branch","created_at","updated_at","deployment_config","attack_mode","ai_write_actions_enabled","error_source_context_enabled","enable_preview_environments","preview_envs_on_demand","preview_envs_idle_timeout_seconds","preview_envs_wake_timeout_seconds","source_type","cross_project_trace_sharing"],"properties":{"ai_alert_summaries_enabled":{"type":["boolean","null"],"description":"Opt-in to AI summarization of metric alert notifications (NULL/false = off)."},"ai_debug_chat_enabled":{"type":["boolean","null"],"description":"Opt-in to AI debugging chat, e.g. on deployment failures (NULL/false = off)."},"ai_write_actions_enabled":{"type":"boolean","description":"Opt-in to AI propose-then-confirm write capability (false = off)."},"attack_mode":{"type":"boolean","description":"Attack mode - when enabled, requires CAPTCHA verification for all project environments"},"created_at":{"type":"integer","format":"int64"},"cross_project_trace_sharing":{"type":"boolean","description":"ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed\nfrom cross-project discovery results. Default true (consistent with the\nOSS global-observability model where any OtelRead holder can query any\nproject's telemetry)."},"deployment_config":{"$ref":"#/components/schemas/DeploymentConfig","description":"Deployment configuration (resources, autoscaling, features)"},"directory":{"type":"string"},"enable_preview_environments":{"type":"boolean","description":"Enable automatic preview environment creation for each branch"},"error_source_context_enabled":{"type":"boolean","description":"Opt-in to native error-tracking source context (false = off). When on,\nTemps stores uploaded source files and shows source code in stack traces."},"error_source_root":{"type":["string","null"],"description":"Where auto-capture reads source from (relative to the checkout). Null =\nthe deployment's Docker build context."},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"],"description":"Git clone URL for the repository (used for public repos without a provider connection)"},"gitlab_webhook_id":{"type":["integer","null"],"format":"int32","description":"GitLab webhook ID installed on the connected repository.\n`null` when no GitLab webhook is installed (not connected to GitLab,\nor webhook was removed / never created).","example":42},"id":{"type":"integer","format":"int32"},"last_deployment":{"type":["integer","null"],"format":"int64"},"main_branch":{"type":"string"},"name":{"type":"string"},"preset":{"type":["string","null"]},"preset_config":{"description":"Preset-specific configuration (Dockerfile path, build context, etc.)"},"preview_envs_idle_timeout_seconds":{"type":"integer","format":"int32","description":"Idle timeout (seconds) for on-demand preview environments."},"preview_envs_on_demand":{"type":"boolean","description":"When true, newly-created preview environments default to on-demand mode\n(containers stop after the configured idle timeout to save resources)."},"preview_envs_wake_timeout_seconds":{"type":"integer","format":"int32","description":"Wake timeout (seconds) for on-demand preview environments."},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"slug":{"type":"string"},"source_type":{"$ref":"#/components/schemas/SourceType","description":"Source type for deployments (git, docker_image, or static_files)"},"updated_at":{"type":"integer","format":"int64"}}},"ProjectSecretEnvironmentInfo":{"type":"object","required":["id","name","main_url"],"properties":{"id":{"type":"integer","format":"int32"},"main_url":{"type":"string"},"name":{"type":"string"}}},"ProjectSecretResponse":{"type":"object","description":"Project secret metadata. There is deliberately no `value` field — secret\nplaintext is never returned after creation. Callers that need the value\nmust read it from the mounted file inside the container.","required":["id","project_id","key","include_in_preview","created_at","updated_at","environments"],"properties":{"created_at":{"type":"integer","format":"int64"},"environments":{"type":"array","items":{"$ref":"#/components/schemas/ProjectSecretEnvironmentInfo"}},"id":{"type":"integer","format":"int32"},"include_in_preview":{"type":"boolean"},"key":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"integer","format":"int64"}}},"ProjectServiceInfo":{"type":"object","required":["id","project","service"],"properties":{"id":{"type":"integer","format":"int32"},"project":{"$ref":"#/components/schemas/ProjectInfo"},"service":{"$ref":"#/components/schemas/ExternalServiceInfo"}}},"ProjectStatisticsResponse":{"type":"object","required":["total_count"],"properties":{"total_count":{"type":"integer","format":"int64"}}},"ProjectStatsBreakdown":{"type":"object","required":["project_id","unique_visitors","total_visits","total_page_views","bounce_rate","engagement_rate"],"properties":{"bounce_rate":{"type":"number","format":"double"},"engagement_rate":{"type":"number","format":"double"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":["string","null"]},"total_page_views":{"type":"integer","format":"int64"},"total_visits":{"type":"integer","format":"int64"},"unique_visitors":{"type":"integer","format":"int64"}}},"ProjectType":{"type":"string","description":"Project type enumeration","enum":["static","docker","buildpack","git"]},"ProjectUsageInfoResponse":{"type":"object","required":["id","name","slug","connection_id","connection_name"],"properties":{"connection_id":{"type":"integer","format":"int32"},"connection_name":{"type":"string"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"ProjectsHealthResponse":{"type":"object","description":"Batch health summary response","required":["projects"],"properties":{"projects":{"type":"object","description":"Health summaries keyed by project ID","additionalProperties":{"$ref":"#/components/schemas/ProjectHealthSummary"},"propertyNames":{"type":"string"}}}},"ProjectsMonitorHealthResponse":{"type":"object","description":"Batch response for projects health","required":["projects"],"properties":{"projects":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ProjectMonitorHealth"},"propertyNames":{"type":"string"}}}},"PromoteDeploymentRequest":{"type":"object","required":["target_environment_id"],"properties":{"target_environment_id":{"type":"integer","format":"int32","description":"Target environment ID to promote the deployment to"}}},"PropertyBreakdownItem":{"type":"object","required":["value","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"value":{"type":"string"}}},"PropertyBreakdownQuery":{"type":"object","description":"Query parameters for property breakdown (group by column)","required":["start_date","end_date","group_by"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"event_name":{"type":["string","null"],"description":"Optional event name filter (e.g., \"page_view\", \"click\")"},"filter_browser":{"type":["string","null"],"description":"Filter by browser name (for browser version drill-downs)"},"filter_channel":{"type":["string","null"],"description":"Filter by channel name (for channel -> referrer drill-downs)"},"filter_country":{"type":["string","null"],"description":"Filter by country (for region/city drill-downs). Requires geolocation join."},"filter_os":{"type":["string","null"],"description":"Filter by operating system name (for OS version drill-downs)"},"filter_referrer":{"type":["string","null"],"description":"Filter by referrer hostname (for referrer -> pages drill-downs)"},"filter_region":{"type":["string","null"],"description":"Filter by region (for city drill-downs). Requires geolocation join."},"group_by":{"$ref":"#/components/schemas/PropertyColumn","description":"Property column to group by"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of results to return (default: 20, max: 100)"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"PropertyBreakdownResponse":{"type":"object","required":["property","items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PropertyBreakdownItem"}},"property":{"type":"string"},"total":{"type":"integer","format":"int64"}}},"PropertyColumn":{"type":"string","enum":["channel","device_type","browser","browser_version","operating_system","operating_system_version","utm_source","utm_medium","utm_campaign","utm_term","utm_content","referrer_hostname","language","event_type","event_name","page_path","pathname","country","region","city"]},"PropertyTimelineItem":{"type":"object","required":["timestamp","value","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"},"value":{"type":"string"}}},"PropertyTimelineQuery":{"type":"object","description":"Query parameters for property timeline (group by column over time)","required":["start_date","end_date","group_by"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level"},"bucket_size":{"type":["string","null"],"description":"Time bucket size: \"hour\", \"day\", \"week\", \"month\" (default: auto-detect)"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"event_name":{"type":["string","null"],"description":"Optional event name filter"},"group_by":{"$ref":"#/components/schemas/PropertyColumn","description":"Property column to group by"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"PropertyTimelineResponse":{"type":"object","required":["property","bucket_size","items"],"properties":{"bucket_size":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PropertyTimelineItem"}},"property":{"type":"string"}}},"Protocol":{"type":"string","description":"Network protocol","enum":["tcp","udp"]},"ProviderCatalogDto":{"type":"object","description":"One catalog entry rendered for the settings UI.","required":["id","name","install_command","auth_command","auth_flavors","models","credential_saved","supports_max_turns"],"properties":{"auth_command":{"type":"string"},"auth_flavors":{"type":"array","items":{"$ref":"#/components/schemas/AuthFlavorDto"}},"credential_saved":{"type":"boolean","description":"True when a credential is currently saved for this provider in the\nsettings JSON. Lets the UI render \"Configured\" badges without the\nfrontend having to inspect the encrypted blob."},"current_auth_type":{"type":["string","null"],"description":"Currently saved auth flavor id (when `credential_saved` is true).\n`None` when no credential is saved yet."},"default_model":{"type":["string","null"],"description":"Currently saved default model id for this provider, if one was\npicked. `None` means \"use the CLI's own default\" — the UI renders\nthat as \"Use provider default\"."},"id":{"type":"string"},"install_command":{"type":"string"},"max_turns_analysis":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer analysis phase. `None` = built-in\ndefault (10). Only enforced for CLIs with a turn flag (Claude Code)."},"max_turns_feedback":{"type":["integer","null"],"format":"int32","description":"Default max turns for autofixer feedback rounds. `None` = built-in\ndefault (10)."},"max_turns_fix":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer fix phase. `None` = built-in\ndefault (20)."},"models":{"type":"array","items":{"type":"string"},"description":"Model ids this provider accepts, in display order. The first entry is\nthe recommended default. Empty when the provider doesn't expose model\nselection (e.g. OpenCode), which the UI uses to hide the dropdown."},"name":{"type":"string"},"supports_max_turns":{"type":"boolean","description":"True when this provider's CLI supports enforcing a turn cap. False\nfor Codex/OpenCode, which run to completion — the UI labels their\nmax-turns inputs accordingly."}}},"ProviderCatalogResponse":{"type":"object","required":["default_provider","providers"],"properties":{"default_provider":{"type":"string","description":"Active provider id from `agent_sandbox.default_provider`. The settings\nUI uses this to highlight which card is the active one."},"providers":{"type":"array","items":{"$ref":"#/components/schemas/ProviderCatalogDto"}}}},"ProviderConfig":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/StripeConfig"},{"type":"object","required":["provider"],"properties":{"provider":{"type":"string","enum":["stripe"]}}}]},{"allOf":[{"$ref":"#/components/schemas/LemonSqueezyConfig"},{"type":"object","required":["provider"],"properties":{"provider":{"type":"string","enum":["lemon_squeezy"]}}}]}],"description":"Provider-specific integration settings persisted in\n`revenue_integrations.config`.\n\nThe tag is the lowercase provider name, so adding a new provider\nmeans adding a new variant and the existing rows are untouched.\nOld rows (pre-config) and rows with `NULL` config are treated as\n\"accept all events, no filtering\" via [`ProviderConfig::default_for`]."},"ProviderConfigMasked":{"type":"object","required":["auth_type","credential_saved","extra"],"properties":{"auth_type":{"type":"string"},"credential_saved":{"type":"boolean","description":"True if a credential is stored for this provider. The encrypted blob\nis never returned over HTTP."},"default_model":{"type":["string","null"]},"extra":{}}},"ProviderDeletionCheckResponse":{"type":"object","required":["can_delete","projects_in_use","message"],"properties":{"can_delete":{"type":"boolean"},"message":{"type":"string"},"projects_in_use":{"type":"array","items":{"$ref":"#/components/schemas/ProjectUsageInfoResponse"}}}},"ProviderDescriptor":{"type":"object","required":["name","display_name","recommended_events"],"properties":{"display_name":{"type":"string"},"name":{"type":"string"},"recommended_events":{"type":"array","items":{"type":"string"}}}},"ProviderKeyResponse":{"type":"object","required":["id","provider","display_name","api_key_masked","is_active","created_at","updated_at"],"properties":{"api_key_masked":{"type":"string","description":"Masked API key (only last 4 chars visible)"},"base_url":{"type":["string","null"]},"created_at":{"type":"string"},"default_model":{"type":["string","null"],"description":"Model id this provider serves (NULL → per-provider default)."},"display_name":{"type":"string"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"provider":{"type":"string"},"updated_at":{"type":"string"}}},"ProviderMetadata":{"type":"object","required":["service_type","display_name","description","icon_url","color"],"properties":{"color":{"type":"string","example":"#336791"},"description":{"type":"string","example":"Relational database management system"},"display_name":{"type":"string","example":"PostgreSQL"},"icon_url":{"type":"string","example":"https://cdn.simpleicons.org/postgresql"},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"}}},"ProviderResponse":{"type":"object","required":["id","name","provider_type","auth_method","is_active","is_default","created_at","updated_at"],"properties":{"auth_method":{"type":"string"},"base_url":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"is_default":{"type":"boolean"},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"ProviderUsage":{"type":"object","required":["provider","request_count","input_tokens","output_tokens","avg_latency_ms","error_count"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"input_tokens":{"type":"integer","format":"int64"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_count":{"type":"integer","format":"int64"}}},"ProvisionResponse":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/DomainError"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["complete"]}}}]},{"allOf":[{"$ref":"#/components/schemas/DomainChallengeResponse"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["pending"]}}}]}]},"ProxyLogResponse":{"type":"object","description":"Response model for proxy logs","required":["id","timestamp","method","path","host","status_code","request_source","is_system_request","routing_status","request_id"],"properties":{"bot_name":{"type":["string","null"]},"browser":{"type":["string","null"]},"browser_version":{"type":["string","null"]},"cache_status":{"type":["string","null"]},"client_ip":{"type":["string","null"]},"container_id":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"host":{"type":"string"},"id":{"type":"integer","format":"int32"},"ip_geolocation_id":{"type":["integer","null"],"format":"int32"},"is_bot":{"type":["boolean","null"]},"is_system_request":{"type":"boolean"},"method":{"type":"string"},"operating_system":{"type":["string","null"]},"path":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"query_string":{"type":["string","null"]},"referrer":{"type":["string","null"]},"request_id":{"type":"string"},"request_size_bytes":{"type":["integer","null"],"format":"int64"},"request_source":{"type":"string"},"response_size_bytes":{"type":["integer","null"],"format":"int64"},"response_time_ms":{"type":["integer","null"],"format":"int32"},"routing_status":{"type":"string"},"session_id":{"type":["integer","null"],"format":"int32"},"status_code":{"type":"integer","format":"int32"},"timestamp":{"type":"string"},"upstream_host":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"ProxyLogsPaginatedResponse":{"type":"object","description":"Paginated response for proxy logs","required":["logs","total","page","page_size","total_pages"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/ProxyLogResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0},"total_pages":{"type":"integer","format":"int64","minimum":0}}},"ProxyRequest":{"type":"object","description":"Proxy configuration for email validation","required":["host","port"],"properties":{"host":{"type":"string","description":"Proxy host","example":"proxy.example.com"},"password":{"type":["string","null"],"description":"Optional proxy password"},"port":{"type":"integer","format":"int32","description":"Proxy port","example":1080,"minimum":0},"username":{"type":["string","null"],"description":"Optional proxy username"}}},"PublicHostnameStrategy":{"type":"string","description":"Public hostname generation mode for Temps-managed preview routes.\n\nThe mode is stored per managed domain (`dns_managed_domains.generated_hostname_mode`)\nrather than globally, so a provider such as Cloudflare can offer the flat layout\nrequired by its Universal SSL wildcard cert without changing every domain's behaviour.","enum":["standard","flat"]},"PublicPresetResponse":{"type":"object","description":"Response for preset detection","required":["branch","presets"],"properties":{"branch":{"type":"string","description":"Branch name where presets were detected"},"presets":{"type":"array","items":{"$ref":"#/components/schemas/PresetInfo"},"description":"List of detected presets"}}},"PublicRepositoryInfo":{"type":"object","description":"Public repository information","required":["owner","name","full_name","default_branch","stars","forks"],"properties":{"default_branch":{"type":"string","description":"Default branch name"},"description":{"type":["string","null"],"description":"Repository description"},"forks":{"type":"integer","format":"int32","description":"Fork count"},"full_name":{"type":"string","description":"Full repository name (owner/repo)"},"language":{"type":["string","null"],"description":"Primary programming language"},"name":{"type":"string","description":"Repository name"},"owner":{"type":"string","description":"Repository owner"},"stars":{"type":"integer","format":"int32","description":"Star count"}}},"PurgeLogsRequest":{"type":"object","required":["before"],"properties":{"before":{"type":"string","description":"Delete all logs before this timestamp (ISO 8601)"}}},"PushImageRequest":{"type":"object","description":"Request to push an external image","required":["image_ref"],"properties":{"image_ref":{"type":"string"},"metadata":{}}},"PushedExternalImageResponse":{"type":"object","description":"Response for in-memory external image operations (legacy push flow).\n\nRenamed to avoid shadowing the richer database-backed `ExternalImageResponse`\nin `handlers/remote_deployments.rs`. The two types serve different routes\n(`/images` ephemeral push vs `/external-images` registered images).","required":["id","image_ref","pushed_at"],"properties":{"digest":{"type":["string","null"]},"id":{"type":"string"},"image_ref":{"type":"string"},"pushed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"size":{"type":["integer","null"],"format":"int64","minimum":0}}},"QueryDataRequest":{"type":"object","properties":{"filters":{"description":"JSON filters (backend-specific format)"},"limit":{"type":"integer","description":"Maximum number of rows to return","example":100,"minimum":0},"offset":{"type":"integer","description":"Number of rows to skip","example":0,"minimum":0},"sort_by":{"type":["string","null"],"description":"Sort by field name"},"sort_order":{"type":["string","null"],"description":"Sort order (asc/desc)"}}},"QueryDataResponse":{"type":"object","required":["fields","rows","total_count","returned_count","execution_time_ms"],"properties":{"execution_time_ms":{"type":"integer","format":"int64","description":"Query execution time in milliseconds","example":45,"minimum":0},"fields":{"type":"array","items":{"$ref":"#/components/schemas/FieldResponse"},"description":"Field definitions"},"returned_count":{"type":"integer","description":"Number of rows returned in this response","example":100,"minimum":0},"rows":{"type":"array","items":{},"description":"Data rows (array of JSON objects)"},"total_count":{"type":"integer","format":"int64","description":"Total number of rows matching the query (before limit/offset)","example":1234,"minimum":0}}},"QuotaResponse":{"type":"object","required":["quota"],"properties":{"quota":{"$ref":"#/components/schemas/StorageQuota"}}},"RateLimitConfig":{"type":"object","description":"Rate limiting configuration (subset of global RateLimitSettings)","properties":{"blacklistIps":{"type":"array","items":{"type":"string"},"description":"Blacklist specific IPs for this project/environment"},"maxRequestsPerHour":{"type":["integer","null"],"format":"int32","description":"Override rate limit per hour","minimum":0},"maxRequestsPerMinute":{"type":["integer","null"],"format":"int32","description":"Override rate limit per minute","minimum":0},"whitelistIps":{"type":"array","items":{"type":"string"},"description":"Whitelist specific IPs for this project/environment"}}},"RateLimitSettings":{"type":"object","properties":{"blacklist_ips":{"type":"array","items":{"type":"string"},"default":[]},"enabled":{"type":"boolean","default":false},"max_requests_per_hour":{"type":"integer","format":"int32","default":1000,"minimum":0},"max_requests_per_minute":{"type":"integer","format":"int32","default":60,"minimum":0},"whitelist_ips":{"type":"array","items":{"type":"string"},"default":[]}}},"ReachabilityStatus":{"type":"string","description":"Email reachability status","enum":["safe","risky","invalid","unknown"]},"ReadFileResponse":{"type":"object","required":["path","contents_b64","size"],"properties":{"contents_b64":{"type":"string","description":"File contents, base64-encoded. Symmetric with `WriteFileBody`."},"path":{"type":"string"},"size":{"type":"integer","format":"int64","minimum":0}}},"RecentActivityQuery":{"type":"object","description":"Query parameters for recent activity endpoint","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32","description":"Environment ID (optional)"},"limit":{"type":["integer","null"],"format":"int32","description":"Max number of events to return (default: 50, max: 100)"},"project_id":{"type":"integer","format":"int32","description":"Project ID"},"since_id":{"type":["integer","null"],"format":"int64","description":"Return events with ID greater than this (for cursor-based polling)"}}},"RecentActivityResponse":{"type":"object","description":"Response for recent activity events endpoint","required":["events","count"],"properties":{"count":{"type":"integer","description":"Total events returned","minimum":0},"events":{"type":"array","items":{"$ref":"#/components/schemas/ActivityEvent"},"description":"Recent events, newest first"}}},"RecentEventResponse":{"type":"object","required":["occurred_at","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"event_type":{"type":"string"},"mrr_minor":{"type":["integer","null"],"format":"int64"},"occurred_at":{"type":"string","format":"date-time"}}},"RecentQueryParams":{"type":"object","properties":{"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"cost_gt":{"type":["integer","null"],"format":"int64","description":"Cost strictly greater-than, in microcents"},"cost_gte":{"type":["integer","null"],"format":"int64","description":"Cost greater-than-or-equal, in microcents"},"cost_lt":{"type":["integer","null"],"format":"int64","description":"Cost strictly less-than, in microcents"},"cost_lte":{"type":["integer","null"],"format":"int64","description":"Cost less-than-or-equal, in microcents"},"limit":{"type":["integer","null"],"format":"int64","description":"Page size (defaults to 20, max 50)","minimum":0},"model":{"type":["string","null"],"description":"Filter by model name"},"offset":{"type":["integer","null"],"format":"int64","description":"Number of results to skip for pagination (defaults to 0)","minimum":0},"provider":{"type":["string","null"],"description":"Filter by provider name"},"status":{"type":["integer","null"],"format":"int32","description":"Filter by HTTP status code (exact match)"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"tokens_gt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly greater-than"},"tokens_gte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) greater-than-or-equal"},"tokens_lt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly less-than"},"tokens_lte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) less-than-or-equal"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"RecordListResponse":{"type":"object","description":"Record list response","required":["records"],"properties":{"records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecord"}}}},"RecoveryTarget":{"oneOf":[{"type":"object","description":"Recover to a specific timestamp.","required":["time","kind"],"properties":{"kind":{"type":"string","enum":["time"]},"time":{"type":"string","format":"date-time"}}},{"type":"object","description":"Recover to a specific transaction id (Postgres).","required":["xid","kind"],"properties":{"kind":{"type":"string","enum":["xid"]},"xid":{"type":"string"}}},{"type":"object","description":"Recover to a specific log sequence number (Postgres).","required":["lsn","kind"],"properties":{"kind":{"type":"string","enum":["lsn"]},"lsn":{"type":"string"}}},{"type":"object","description":"Recover to a named restore point created via `pg_create_restore_point` (Postgres).","required":["name","kind"],"properties":{"kind":{"type":"string","enum":["name"]},"name":{"type":"string"}}}],"description":"Engine-specific recovery target for PITR.\n\nPostgres honors all variants; Redis/Mongo/S3 will likely reject non-Time\nvariants or define their own semantics when they grow PITR support."},"ReferrerCount":{"type":"object","required":["referrer","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"referrer":{"type":"string"}}},"ReferrersAnalyticsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"RegenerateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]}}},"RegisterImageRequest":{"type":"object","required":["image_ref"],"properties":{"digest":{"type":["string","null"],"description":"Image digest (sha256:...)","example":"sha256:abc123def456"},"image_ref":{"type":"string","description":"Docker image reference (e.g., \"ghcr.io/org/app:v1.0\")","example":"ghcr.io/myorg/myapp:v1.0"},"metadata":{"description":"Additional metadata"},"tag":{"type":["string","null"],"description":"Image tag","example":"v1.0"}}},"RegisterNodeApiRequest":{"type":"object","required":["name","token","address","private_address"],"properties":{"address":{"type":"string","description":"Node's reachable address (e.g., \"10.100.0.2\" or \"192.168.1.50\")"},"architecture":{"type":["string","null"],"description":"Container platform of this node's Docker daemon (`linux/amd64`,\n`linux/arm64`). Optional: agents older than multi-arch support omit it\nand the value is learned from the first heartbeat instead."},"csr_pem":{"type":["string","null"],"description":"Node-generated certificate signing request (PEM) for multi-node mTLS\n(ADR-020 WS-2.1). When present, the control plane signs it with the\ncluster CA and returns the leaf + CA cert. Optional — token-only nodes\n(legacy / edge) still register without one."},"edge_public_key":{"type":["string","null"],"description":"X25519 public key for ECIES certificate encryption (base64-encoded, edge nodes only)"},"join_token":{"type":["string","null"],"description":"Join token to authorize this registration (must match the token generated in Settings)"},"labels":{"description":"Labels for scheduling (e.g., {\"region\": \"us-east\", \"gpu\": \"true\"})"},"name":{"type":"string","description":"Unique name for this node"},"prior_token":{"type":["string","null"],"description":"The node's *current* token, supplied to prove possession when\nre-registering (changing the identity of) a node that already exists.\nOptional; only needed to rebind a still-live node. (ADR-020 WS-1.2.)"},"private_address":{"type":"string","description":"Private/WireGuard address for inter-node communication"},"public_endpoint":{"type":["string","null"],"description":"Public endpoint for WireGuard (e.g., \"203.0.113.1:51820\")"},"role":{"type":["string","null"],"description":"Node role (default: \"worker\")"},"token":{"type":"string","description":"Registration token (plaintext, will be hashed before storage)"},"wg_public_key":{"type":["string","null"],"description":"WireGuard public key"}}},"RegisterNodeResponse":{"type":"object","required":["id","name","status","message"],"properties":{"ca_cert_pem":{"type":["string","null"],"description":"The cluster CA certificate (PEM) the node pins as its trust root.\nPresent only when a `csr_pem` was supplied. (ADR-020 WS-2.1.)"},"cert_pem":{"type":["string","null"],"description":"The signed per-node leaf certificate (PEM) the agent serves as its TLS\nserver cert. Present only when a `csr_pem` was supplied. (ADR-020 WS-2.1.)"},"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"RegisterRequest":{"type":"object","required":["email","password","name"],"properties":{"email":{"type":"string"},"name":{"type":"string"},"password":{"type":"string"}}},"ReinstallWebhookResponse":{"type":"object","description":"Response for `POST /projects/{project_id}/gitlab/reinstall-webhook`","required":["hook_id","message"],"properties":{"hook_id":{"type":"integer","format":"int32","description":"The new GitLab hook ID that was installed."},"message":{"type":"string","description":"Human-readable status message."}}},"ReleaseListResponse":{"type":"object","required":["releases"],"properties":{"releases":{"type":"array","items":{"type":"string"}}}},"ReloadResponse":{"type":"object","description":"Response from the reload endpoint.","required":["loaded","plugins","message"],"properties":{"loaded":{"type":"integer","description":"Number of plugins successfully loaded after reload","minimum":0},"message":{"type":"string","description":"Human-readable status message"},"plugins":{"type":"array","items":{"type":"string"},"description":"Names of loaded plugins"}}},"RemoteDeploymentResponse":{"type":"object","required":["id","project_id","environment_id","slug","state","source_type","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"slug":{"type":"string"},"source_type":{"type":"string"},"state":{"type":"string"}}},"RemoveNodeResponse":{"type":"object","required":["id","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"}}},"RenameConversationRequest":{"type":"object","required":["title"],"properties":{"title":{"type":"string","description":"New human-facing title. Trimmed; must be non-empty after trimming."}}},"RepositoryListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"language":{"type":["string","null"]},"owner":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"private":{"type":["boolean","null"]},"search":{"type":["string","null"]},"sort":{"type":["string","null"]}}},"RepositoryListResponse":{"type":"object","required":["repositories","total_count"],"properties":{"repositories":{"type":"array","items":{"$ref":"#/components/schemas/RepositoryResponse"}},"total_count":{"type":"integer","minimum":0}}},"RepositoryPresetResponse":{"type":"object","required":["repository_id","owner","name","presets","calculated_at"],"properties":{"calculated_at":{"type":"string","format":"date-time"},"name":{"type":"string"},"owner":{"type":"string"},"presets":{"type":"array","items":{"$ref":"#/components/schemas/ProjectPresetResponse"}},"repository_id":{"type":"integer","format":"int32"}}},"RepositoryResponse":{"type":"object","required":["id","owner","name","full_name","private","default_branch","created_at","updated_at","pushed_at","git_provider_connection_id"],"properties":{"clone_url":{"type":["string","null"],"description":"HTTPS clone URL (e.g., https://github.com/owner/repo.git)"},"created_at":{"type":"string","format":"date-time"},"default_branch":{"type":"string"},"description":{"type":["string","null"]},"full_name":{"type":"string"},"git_provider_connection_id":{"type":"integer","format":"int32","description":"ID of the git provider connection this repository was synced from."},"id":{"type":"integer","format":"int32"},"language":{"type":["string","null"]},"name":{"type":"string"},"owner":{"type":"string"},"preset":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ProjectPresetResponse"}},"private":{"type":"boolean"},"pushed_at":{"type":"string","format":"date-time"},"ssh_url":{"type":["string","null"],"description":"SSH clone URL (e.g., git@github.com:owner/repo.git)"},"updated_at":{"type":"string","format":"date-time"}}},"RepositorySyncStartedResponse":{"type":"object","description":"Returned by `POST /git-connections/{id}/sync` to acknowledge that a\nsync has been kicked off in the background. Clients should poll the\nconnection's `syncing` and `synced_repository_count` fields to track\nprogress rather than waiting on this response.","required":["connection_id","syncing","started_at"],"properties":{"connection_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time"},"syncing":{"type":"boolean"}}},"RequestRow":{"type":"object","required":["id","ts","method","host","path","status","request_headers","response_headers","headers_truncated"],"properties":{"client_ip":{"type":["string","null"]},"country":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_group_id":{"type":["integer","null"],"format":"int32"},"headers_truncated":{"type":"boolean"},"host":{"type":"string"},"id":{"type":"string","description":"The request's unique `request_id` (assigned by the proxy). Used as the\nrow identity instead of the storage PK because the ClickHouse backend\nhas no serial id (rows come back with `id = 0`) while `request_id` is\nunique and present on both backends."},"latency_ms":{"type":["integer","null"],"format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"query_string":{"type":["string","null"]},"referrer":{"type":["string","null"]},"request_headers":{},"response_headers":{},"status":{"type":"integer","format":"int32"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"},"user_agent":{"type":["string","null"]}}},"ResetPasswordRequest":{"type":"object","required":["token","new_password"],"properties":{"new_password":{"type":"string"},"token":{"type":"string"}}},"ResizeSandboxBody":{"type":"object","required":["disk_size_mb"],"properties":{"disk_size_mb":{"type":"integer","format":"int64","description":"New root disk size in MB. Grow-only; must exceed the current size.","minimum":0}},"additionalProperties":false},"ResolvedEnvVarResponse":{"type":"object","description":"One entry in the computed env-var view that merges manual and integration\nsources and tags each result with its origin. `value_preview` is always\nmasked — plaintext must be fetched per-key via the existing reveal endpoint,\nwhich is audit-logged.","required":["key","value_preview","source","environments","include_in_preview"],"properties":{"environments":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentInfo"},"description":"Environments this var applies to. For integration-sourced vars this\nreflects every environment of the project (integrations are global)."},"include_in_preview":{"type":"boolean","description":"Whether the var would be auto-applied to preview environments.\nIntegration vars always surface in preview; manual vars follow the flag."},"key":{"type":"string"},"source":{"$ref":"#/components/schemas/ResolvedEnvVarSource"},"value_preview":{"type":"string","description":"Masked or truncated preview. Never the raw value."}}},"ResolvedEnvVarSource":{"oneOf":[{"type":"object","description":"Manually-defined env var. If `overrides_service` is set, this key would\notherwise have been supplied by an integration — the UI should show the\nintegration icon plus an \"overridden\" indicator.","required":["var_id","type"],"properties":{"overrides_service":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/EnvVarIntegrationInfo"}]},"type":{"type":"string","enum":["manual"]},"var_id":{"type":"integer","format":"int32"}}},{"type":"object","description":"Supplied by a linked external service (Postgres, Redis, S3, etc.).","required":["service","type"],"properties":{"service":{"$ref":"#/components/schemas/EnvVarIntegrationInfo"},"type":{"type":"string","enum":["integration"]}}}],"description":"Where a resolved env var comes from. Integration-sourced vars may be\n\"shadowed\" by a manual entry with the same key, in which case the response\ncarries `Manual` with `overrides_service` populated so the UI can still show\nthe integration icon."},"ResourceCounts":{"type":"object","description":"Quick count of resources involved in the migration","required":["projects","environments","deployments","environment_variables","services","domains"],"properties":{"deployments":{"type":"integer","minimum":0},"domains":{"type":"integer","minimum":0},"environment_variables":{"type":"integer","minimum":0},"environments":{"type":"integer","minimum":0},"projects":{"type":"integer","minimum":0},"services":{"type":"integer","minimum":0}}},"ResourceFootprint":{"type":"object","description":"A CPU + memory footprint (requests or measured usage)","required":["cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"CPU in millicores"},"memory_mb":{"type":"integer","format":"int64","description":"Memory in MB"}}},"ResourceInfo":{"type":"object","description":"Resource attributes extracted from OTel resource descriptors.","required":["service_name","attributes"],"properties":{"attributes":{"type":"object"},"deployment_environment":{"type":["string","null"]},"service_name":{"type":"string"},"service_version":{"type":["string","null"]}}},"ResourceLimitApplyResult":{"type":"object","description":"Per-container outcome of a live `docker update` call. Surfaced from the\nPATCH /resources endpoint so the UI can tell the operator whether the\nnew caps are already in effect or whether they only apply on next\nrecreate (e.g., container was missing).","required":["role","container_name","outcome"],"properties":{"container_name":{"type":"string"},"error":{"type":["string","null"],"description":"Populated only when `outcome == \"failed\"`."},"outcome":{"type":"string","description":"One of:\n- \"applied\" — Docker accepted the update; caps are live now.\n- \"missing\" — container does not exist; caps stored, will apply on next start.\n- \"stopped\" — container exists but isn't running; Docker still\n accepts the update (the new caps apply on next start).\n- \"failed\" — `docker update` returned an error (see `error`)."},"role":{"type":"string","description":"`service_members.role` for cluster members; \"standalone\" otherwise."}}},"ResourceLimits":{"type":"object","description":"Resource limits and requests","properties":{"cpu_limit":{"type":["integer","null"],"format":"int32","description":"CPU limit (millicores)"},"cpu_request":{"type":["integer","null"],"format":"int32","description":"CPU request (millicores)"},"memory_limit":{"type":["integer","null"],"format":"int32","description":"Memory limit (MB)"},"memory_request":{"type":["integer","null"],"format":"int32","description":"Memory request (MB)"}}},"ResourceLimitsResponse":{"type":"object","description":"Container resource limits","properties":{"cpu_limit":{"type":["integer","null"],"format":"int32"},"cpu_request":{"type":["integer","null"],"format":"int32"},"memory_limit":{"type":["integer","null"],"format":"int32"},"memory_request":{"type":["integer","null"],"format":"int32"}}},"ResourceLimitsUpdateResponse":{"type":"object","description":"Response from PATCH /external-services/{id}/resources.","required":["limits","applied"],"properties":{"applied":{"type":"array","items":{"$ref":"#/components/schemas/ResourceLimitApplyResult"},"description":"Per-container result of trying to apply the limits live."},"limits":{"$ref":"#/components/schemas/ServiceResourceLimits","description":"The limits that were persisted to the encrypted config."}}},"ResourcesBody":{"type":"object","description":"Nested `resources: { memory, vcpus }` as sent by `@vercel/sandbox`.\n`memory` is in MB, `vcpus` is fractional CPU count.","properties":{"memory":{"type":["integer","null"],"format":"int64","minimum":0},"vcpus":{"type":["number","null"],"format":"double"}}},"RestoreCapabilities":{"type":"object","description":"Capabilities a service exposes for the generic restore framework.\n\nEach engine overrides `ExternalService::restore_capabilities` to declare\nwhat it supports. The handler layer uses this to validate requests and\nthe UI uses it to conditionally show options (e.g., PITR picker).","required":["restore_in_place","restore_to_new_service","pitr"],"properties":{"earliest_pitr_time":{"type":["string","null"],"format":"date-time","description":"Earliest recoverable timestamp, if `pitr` is true. Derived from\nengine-specific archive metadata (e.g., `pg_stat_archiver`)."},"latest_pitr_time":{"type":["string","null"],"format":"date-time","description":"Latest recoverable timestamp, if `pitr` is true."},"pitr":{"type":"boolean","description":"Point-in-time recovery using engine-specific continuous archives\n(WAL for Postgres, AOF for Redis, oplog for MongoDB, object versions for S3)."},"restore_in_place":{"type":"boolean","description":"Restore a backup onto the same running service (destructive)."},"restore_to_new_service":{"type":"boolean","description":"Restore a backup into a freshly provisioned service."}}},"RestoreCapabilitiesResponse":{"allOf":[{"$ref":"#/components/schemas/RestoreCapabilities","description":"Trait-declared capabilities."},{"type":"object","required":["suggested_new_service_name"],"properties":{"suggested_new_service_name":{"type":"string","description":"Suggested name for the new service when creating a clone. Safe to\npre-fill into the UI dialog; the user can edit before submitting."}}}]},"RestorePlan":{"type":"object","description":"Preview of a restore operation. Answers \"what will happen if I click\nstart?\" with engine-level specificity so the user can confirm before\ncommitting to a destructive action.","required":["engine","target_service","source_backup","strategy","steps","warnings","errors","destructive","mode"],"properties":{"destructive":{"type":"boolean","description":"Whether any step overwrites existing data on the target service."},"engine":{"type":"string","description":"Target engine (\"postgres\", etc.)."},"errors":{"type":"array","items":{"type":"string"},"description":"Blocking problems. The UI disables the Start button when non-empty."},"mode":{"type":"string","description":"Echo of the requested mode for the UI."},"source_backup":{"$ref":"#/components/schemas/PlanSourceBackup","description":"Backup we'll read from."},"steps":{"type":"array","items":{"type":"string"},"description":"Ordered list of human-readable actions the orchestrator will take."},"strategy":{"type":"string","description":"How the restore will be performed: \"walg_restore\", \"pg_dump_restore\",\nor \"unsupported\"."},"target_service":{"$ref":"#/components/schemas/PlanTarget","description":"Service we'll operate on (or provision a sibling of)."},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking caveats the user should see (cross-service, empty\nlocation that will be auto-resolved, missing engine metadata, ...)."}}},"RestoreRequestMode":{"oneOf":[{"type":"object","description":"Restore the backup onto the existing service (destructive).","required":["mode"],"properties":{"mode":{"type":"string","enum":["in_place"]}}},{"type":"object","description":"Provision a new service and restore into it.","required":["name","mode"],"properties":{"mode":{"type":"string","enum":["new_service"]},"name":{"type":"string","description":"Name for the new service. Orchestrator auto-suggests\n`{source}-restore-{yyyymmdd-hhmm}` if caller omits, but we require\nan explicit value at the API boundary."},"parameter_overrides":{"description":"Optional parameter overrides (port, docker_image, database)."}}},{"type":"object","description":"Point-in-time recovery. Only valid on WAL-G backups (Postgres).","required":["to_new_service","target","mode"],"properties":{"mode":{"type":"string","enum":["pitr"]},"new_service_name":{"type":["string","null"],"description":"Required when `to_new_service` is true."},"target":{"$ref":"#/components/schemas/RecoveryTarget","description":"Recovery target kind + value."},"to_new_service":{"type":"boolean","description":"Whether PITR restores in place or creates a new service."}}}],"description":"What the caller wants to do. Mirrors `externalsvc::RestoreMode` but\nflattened for JSON over the wire."},"RestoreRunView":{"type":"object","required":["id","source_backup_id","source_service_id","mode","status","phase","created_at"],"properties":{"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"finished_at":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mode":{"type":"string"},"phase":{"type":"string"},"recovery_target":{},"source_backup_id":{"type":"integer","format":"int32"},"source_service_id":{"type":"integer","format":"int32"},"started_at":{"type":["string","null"]},"status":{"type":"string"},"target_service_id":{"type":["integer","null"],"format":"int32"},"target_service_name":{"type":["string","null"]}}},"RetentionCleanupFailure":{"type":"object","required":["backup_id","reason","partial","deleted_objects"],"properties":{"backup_id":{"type":"string"},"deleted_objects":{"type":"integer","format":"int64","minimum":0},"partial":{"type":"boolean"},"reason":{"type":"string"}}},"RetentionCleanupReport":{"type":"object","required":["dry_run","expired","deleted","failed","failures","deleted_backup_ids","deleted_backup_ids_truncated","partially_deleted_backup_ids","partially_deleted_backup_ids_truncated","candidate_backup_ids","candidate_backup_ids_truncated"],"properties":{"candidate_backup_ids":{"type":"array","items":{"type":"string"},"description":"Capped sample of backups selected by the retention policy."},"candidate_backup_ids_truncated":{"type":"boolean"},"deleted":{"type":"integer","format":"int64","minimum":0},"deleted_backup_ids":{"type":"array","items":{"type":"string"},"description":"Capped sample of deleted backup UUIDs for audit attribution."},"deleted_backup_ids_truncated":{"type":"boolean"},"dry_run":{"type":"boolean","description":"True when this report is a non-destructive preview."},"expired":{"type":"integer","format":"int64","minimum":0},"failed":{"type":"integer","format":"int64","minimum":0},"failures":{"type":"array","items":{"$ref":"#/components/schemas/RetentionCleanupFailure"},"description":"Capped diagnostic sample; `failed` remains the authoritative total."},"partially_deleted_backup_ids":{"type":"array","items":{"type":"string"}},"partially_deleted_backup_ids_truncated":{"type":"boolean"},"schedule_id":{"type":["integer","null"],"format":"int32","description":"Schedule scope, or `None` when every schedule was considered."}}},"RetryClusterRequest":{"type":"object","description":"Request body for retrying a failed cluster initialization.","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberRequest"},"description":"Cluster member specifications (same format as create).\nIf omitted, the original member configuration is reconstructed from\nthe preserved service_members records."}}},"RevenueRow":{"type":"object","required":["id","ts","provider","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"provider":{"type":"string"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"RiskLevel":{"type":"string","description":"Risk level for a migration step","enum":["none","low","medium","high","critical"]},"RoleInfo":{"type":"object","description":"Information about a role","required":["name","description","permissions"],"properties":{"description":{"type":"string","description":"Human-readable description of the role"},"name":{"type":"string","description":"The role identifier (e.g., \"admin\")"},"permissions":{"type":"array","items":{"type":"string"},"description":"Permissions included in this role"}}},"RootfsCacheEntry":{"type":"object","description":"A cached rootfs image (Firecracker backend). Digest-keyed build artifact\nshared by all VMs created from the same image.","required":["digest","bytes","referenced_by"],"properties":{"bytes":{"type":"integer","format":"int64","description":"Actual on-disk size in bytes (sparse-aware).","minimum":0},"digest":{"type":"string","description":"Image digest this rootfs was built from (the cache key)."},"referenced_by":{"type":"array","items":{"type":"string"},"description":"IDs of live sandboxes whose per-VM disk was cloned from this entry.\nEmpty means the entry is reclaimable — no sandbox needs it."}}},"RootfsGcReport":{"type":"object","description":"Outcome of a rootfs garbage-collection pass.","required":["removed_digests","freed_bytes"],"properties":{"freed_bytes":{"type":"integer","format":"int64","minimum":0},"removed_digests":{"type":"array","items":{"type":"string"},"description":"Digests of cache entries removed because no sandbox referenced them."}}},"RootfsReport":{"type":"object","description":"Snapshot of a backend's rootfs storage for the management API. Backends\nwithout a rootfs concept (Docker, local) return an empty report.","required":["cache_bytes","cache","vm_bytes","vms"],"properties":{"cache":{"type":"array","items":{"$ref":"#/components/schemas/RootfsCacheEntry"}},"cache_bytes":{"type":"integer","format":"int64","minimum":0},"vm_bytes":{"type":"integer","format":"int64","minimum":0},"vms":{"type":"array","items":{"$ref":"#/components/schemas/RootfsVmEntry"}}}},"RootfsVmEntry":{"type":"object","description":"A per-sandbox rootfs disk (Firecracker backend). One per non-destroyed\nsandbox — the authoritative storage, independent of the cache.","required":["sandbox_name","bytes","running"],"properties":{"bytes":{"type":"integer","format":"int64","minimum":0},"running":{"type":"boolean"},"sandbox_name":{"type":"string"}}},"RouteRefreshResponse":{"type":"object","required":["route_count","message"],"properties":{"message":{"type":"string","description":"Human-readable message"},"route_count":{"type":"integer","description":"Number of routes loaded","minimum":0}}},"RouteResponse":{"type":"object","required":["id","domain","host","port","enabled","route_type","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"enabled":{"type":"boolean"},"host":{"type":"string"},"id":{"type":"integer","format":"int32"},"port":{"type":"integer","format":"int32"},"route_type":{"type":"string","description":"Route type: \"http\" or \"tls\""},"updated_at":{"type":"integer","format":"int64"}}},"RouteRole":{"type":"object","required":["id","name","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64","example":"1683900000000"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"updated_at":{"type":"integer","format":"int64","example":"1683900000000"}}},"RouteUser":{"type":"object","required":["id","name","username","email","image","mfa_enabled","email_verified","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64","example":"1683900000000"},"deleted_at":{"type":["integer","null"],"format":"int64"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"image":{"type":"string"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"integer","format":"int64","example":"1683900000000"},"username":{"type":"string"}}},"RouteUserWithRoles":{"type":"object","required":["user","roles"],"properties":{"roles":{"type":"array","items":{"$ref":"#/components/schemas/RouteRole"}},"user":{"$ref":"#/components/schemas/RouteUser"}}},"RunBackupRequest":{"type":"object","required":["backup_type"],"properties":{"backup_type":{"type":"string","description":"Type of backup to perform","example":"full"}}},"RunExternalServiceBackupRequest":{"type":"object","properties":{"backup_type":{"type":["string","null"],"description":"Type of backup to perform (e.g., \"full\", \"incremental\")","example":"full"},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"ID of the S3 source to store the backup. If omitted, the current default S3 source is used.","example":1}}},"S3ConnectionTestResponse":{"type":"object","description":"Response body for an S3 connection test.","required":["ok","message"],"properties":{"message":{"type":"string","description":"Human-readable message (success confirmation or error detail)."},"ok":{"type":"boolean","description":"Whether the connection and credentials worked."}}},"S3CredentialsResponse":{"type":"object","description":"S3 credentials distributed to agents for backup/restore operations.","required":["access_key_id","secret_key","region","bucket_name","force_path_style"],"properties":{"access_key_id":{"type":"string"},"bucket_name":{"type":"string"},"endpoint":{"type":["string","null"]},"force_path_style":{"type":"boolean"},"region":{"type":"string"},"secret_key":{"type":"string"}}},"S3SourceResponse":{"type":"object","description":"Response type for S3 source","required":["id","name","bucket_name","bucket_path","access_key_id","secret_key","region","is_default","created_at","updated_at"],"properties":{"access_key_id":{"type":"string","example":"AKIAXXXXXXXXXXXXXXXX"},"bucket_name":{"type":"string"},"bucket_path":{"type":"string"},"created_at":{"type":"integer","format":"int64"},"endpoint":{"type":["string","null"],"example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"]},"id":{"type":"integer","format":"int32"},"is_default":{"type":"boolean"},"name":{"type":"string"},"region":{"type":"string"},"secret_key":{"type":"string","writeOnly":true},"updated_at":{"type":"integer","format":"int64"}}},"SandboxDomainResponse":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}},"SandboxEvent":{"type":"object","description":"One entry in a sandbox's operations timeline.","required":["event_type","at"],"properties":{"at":{"type":"integer","format":"int64","description":"Unix epoch milliseconds."},"detail":{"description":"Optional structured context (shape depends on `event_type`)."},"event_type":{"type":"string","description":"Machine-readable operation (`created`, `stopped`, `resumed`,\n`restarted`, `timeout_extended`, `resized`, `preview_password_set`,\n`preview_password_cleared`, `source_seeded`, `destroyed`)."}}},"SandboxEventsResponse":{"type":"object","required":["events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SandboxEvent"}}}},"SandboxInner":{"type":"object","description":"Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —\nthe SDK's zod validator rejects missing required fields.","required":["id","memory","vcpus","region","runtime","timeout","status","requestedAt","createdAt","updatedAt","cwd","name","preview_url_template"],"properties":{"agent_run_id":{"type":["integer","null"],"format":"int32","description":"Agent run this sandbox executes (autofixer / workflow agent).\n`None` for sandboxes created via this API."},"backend":{"type":["string","null"],"description":"Isolation backend: \"docker\" | \"firecracker\". `None` on legacy rows\ncreated before the backend was recorded."},"createdAt":{"type":"integer","format":"int64"},"cwd":{"type":"string"},"disk_size_mb":{"type":["integer","null"],"format":"int64","description":"Configured root disk size in MB (Firecracker). `None` when unknown or\nthe default.","minimum":0},"id":{"type":"string"},"image":{"type":["string","null"]},"memory":{"type":"integer","format":"int64","minimum":0},"name":{"type":"string"},"preview_password_hint":{"type":["string","null"]},"preview_url_template":{"type":"string"},"region":{"type":"string"},"requestedAt":{"type":"integer","format":"int64","description":"Creation time as Unix epoch milliseconds."},"runtime":{"type":"string"},"status":{"type":"string"},"timeout":{"type":"integer","format":"int64","description":"Idle timeout in milliseconds (SDK convention).","minimum":0},"updatedAt":{"type":"integer","format":"int64"},"vcpus":{"type":"number","format":"double"}}},"SandboxResponse":{"type":"object","description":"`@vercel/sandbox` wraps every single-sandbox response as\n`{ sandbox: {...}, routes: [...] }`. The SDK reads both.","required":["sandbox","routes"],"properties":{"routes":{"type":"array","items":{"$ref":"#/components/schemas/SandboxRoute"}},"sandbox":{"$ref":"#/components/schemas/SandboxInner"}}},"SandboxRoute":{"type":"object","description":"A single preview route, one per declared port. We don't know ports\nupfront, so we surface an empty array by default — SDK clients use\ntheir own port when calling `sandbox.domain(port)`.","required":["url","subdomain","port"],"properties":{"port":{"type":"integer","format":"int32","minimum":0},"subdomain":{"type":"string"},"url":{"type":"string"}}},"SandboxStatusResponse":{"type":"object","required":["docker_available","image_ready","image_name","firecracker_available"],"properties":{"docker_available":{"type":"boolean"},"error":{"type":["string","null"]},"firecracker_available":{"type":"boolean"},"image_name":{"type":"string"},"image_ready":{"type":"boolean"}}},"SaveAgentTokenRequest":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"The OAuth token from `claude setup-token` or an API key.\nWill be encrypted before storage."}}},"SaveAgentTokenResponse":{"type":"object","required":["saved"],"properties":{"saved":{"type":"boolean"}}},"SaveCredentialRequest":{"type":"object","required":["auth_type","credential"],"properties":{"auth_type":{"type":"string","description":"Auth flavor id (must match one of the provider's catalog entries)."},"credential":{"type":"string","description":"Plaintext credential body (API key, OAuth token, or full config file\ncontents). Encrypted with `EncryptionService` before being persisted\ninside the `agent_sandbox.providers` JSON map."}}},"SaveCredentialResponse":{"type":"object","required":["saved","provider_id","auth_type"],"properties":{"auth_type":{"type":"string"},"provider_id":{"type":"string"},"saved":{"type":"boolean"}}},"ScalewayCredentialsRequest":{"type":"object","required":["api_key","project_id"],"properties":{"api_key":{"type":"string","example":"scw-secret-key-12345"},"project_id":{"type":"string","example":"12345678-1234-1234-1234-123456789012"}}},"ScanResponse":{"type":"object","required":["id","project_id","scanner_type","status","total_count","critical_count","high_count","medium_count","low_count","unknown_count","started_at","created_at","updated_at"],"properties":{"branch":{"type":["string","null"]},"commit_hash":{"type":["string","null"]},"completed_at":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"created_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"critical_count":{"type":"integer","format":"int32"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"high_count":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"low_count":{"type":"integer","format":"int32"},"medium_count":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"scanner_type":{"type":"string"},"scanner_version":{"type":["string","null"]},"started_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"status":{"type":"string"},"total_count":{"type":"integer","format":"int32"},"unknown_count":{"type":"integer","format":"int32"},"updated_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"}}},"ScheduleRunEntry":{"type":"object","description":"A single run-history entry for the schedule detail page (deliverable 1).\n\nCombines one `backups` row with the most-recent `backup_jobs` row for that\nbackup via a lateral JOIN. Fields from `backup_jobs` are `None` for legacy\nbackup rows that pre-date ADR-014.","required":["backup_id","backup_uuid","state","started_at","s3_location"],"properties":{"attempts":{"type":["integer","null"],"format":"int32","description":"Number of claim-and-run attempts so far. `None` for legacy rows."},"backup_id":{"type":"integer","format":"int32","description":"DB id of the `backups` row."},"backup_uuid":{"type":"string","description":"UUID string (`backups.backup_id`)."},"current_step":{"type":["string","null"],"description":"Last completed step reported by the engine (e.g. `\"upload\"`).\n`None` when no step has been persisted yet."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When the backup finished, if known."},"job_id":{"type":["integer","null"],"format":"int64","description":"Most recent `backup_jobs.id` for this backup. `None` for legacy rows."},"s3_location":{"type":"string","description":"S3 object key or URL where the backup data lives."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Final size in bytes once completed. `None` while running."},"started_at":{"type":"string","description":"When the backup was started (ISO 8601 / RFC 3339)."},"state":{"type":"string","description":"Current state: `\"pending\"`, `\"running\"`, `\"completed\"`, `\"failed\"`."}}},"ScheduleRunJobEntry":{"type":"object","description":"A single job entry inside an expanded schedule run, returned by\n[`BackupService::list_schedule_run_jobs`].","required":["backup_id","backup_uuid","engine","service_name","state","started_at","s3_source_id"],"properties":{"backup_id":{"type":"integer","format":"int32","description":"`backups.id` for this job."},"backup_uuid":{"type":"string","description":"`backups.backup_id` UUID string."},"engine":{"type":"string","description":"Engine key (e.g. `\"control_plane\"`, `\"redis\"`)."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When this child backup finished, if known."},"s3_source_id":{"type":"integer","format":"int32","description":"FK to `s3_sources.id` — needed for the backup detail link."},"service_id":{"type":["integer","null"],"format":"int32","description":"`external_services.id` — `NULL` for the control-plane job."},"service_name":{"type":"string","description":"Name of the external service, or `\"control plane\"` for the\ncontrol-plane job."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes once completed; `None` while running."},"started_at":{"type":"string","description":"When this child backup started (ISO 8601 / RFC 3339)."},"state":{"type":"string","description":"Current state of this child backup."}}},"ScheduleRunListResponse":{"type":"object","description":"Paginated run-history response for a backup schedule (deliverable 1).","required":["runs","total","page","page_size"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page (clamped to 1–100)."},"runs":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunEntry"},"description":"Run entries, newest first."},"total":{"type":"integer","format":"int64","description":"Total number of runs across all pages."}}},"ScheduleRunResponse":{"type":"object","description":"HTTP response body for `POST /api/backups/schedules/{id}/run` (fan-out).","required":["schedule_run_id","jobs"],"properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/EnqueuedJob"},"description":"All jobs that were enqueued in this fan-out."},"schedule_run_id":{"type":"integer","format":"int64","description":"The `schedule_runs.id` of the newly created run."}}},"ScheduleRunSummary":{"type":"object","description":"Summary of one scheduler tick (or one \"Run now\" click), returned by\n[`BackupService::list_schedule_runs`].\n\nThe `aggregate_state` is computed at read time from child backup counts:\n- `\"running\"` — at least one child is `\"pending\"` or `\"running\"`.\n- `\"failed\"` — at least one child is `\"failed\"` and none are running.\n- `\"completed\"` — all children are `\"completed\"`.","required":["run_id","schedule_id","triggered_by","started_at","aggregate_state","total_jobs","completed_jobs","failed_jobs","running_jobs","pending_jobs"],"properties":{"aggregate_state":{"type":"string","description":"Aggregate state computed from child counts (see struct docs)."},"completed_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"completed\"`."},"failed_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When all children reached a terminal state. `None` while any child is\nstill `\"pending\"` or `\"running\"`."},"pending_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"pending\"`."},"run_id":{"type":"integer","format":"int64","description":"`schedule_runs.id` for this tick."},"running_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"running\"`."},"schedule_id":{"type":"integer","format":"int32","description":"FK to `backup_schedules.id`."},"started_at":{"type":"string","description":"When the fan-out started (ISO 8601 / RFC 3339)."},"total_jobs":{"type":"integer","format":"int64","description":"Total number of child backup jobs in this run."},"triggered_by":{"type":"string","description":"How the run was triggered: `\"cron\"` or `\"manual\"`."}}},"ScheduleRunSummaryList":{"type":"object","description":"Paginated list of schedule run summaries returned by the new\n[`BackupService::list_schedule_runs`].","required":["runs","total","page","page_size"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page."},"runs":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunSummary"},"description":"Run summaries, newest first. Includes synthetic single-job rows for\nlegacy `backups` rows that have `schedule_id` set but no\n`schedule_run_id` (pre-fan-out history)."},"total":{"type":"integer","format":"int64","description":"Total number of run entries across all pages."}}},"ScreenshotSettings":{"type":"object","properties":{"enabled":{"type":"boolean","default":false},"provider":{"type":"string","default":"local"},"url":{"type":"string","default":""}}},"SearchLogsRequest":{"type":"object","required":["project_id"],"properties":{"container_ids":{"type":"array","items":{"type":"string"},"description":"Filter to specific containers (Docker container IDs). Empty = all\ncontainers. Drives \"filter by container / show all\" in a project's\nhistory, which spans multiple deployments and containers."},"context_lines":{"type":["integer","null"],"format":"int32","description":"grep -C: number of raw context lines to include before and after each\nmatch (0 = none, default). Clamped to 50 server-side. The surrounding\nlines ignore the level/text filters — they are the actual adjacent log\nlines, merged across overlapping matches.","minimum":0},"cursor":{"type":["string","null"],"description":"Pagination cursor"},"deploy_id":{"type":["integer","null"],"format":"int32","description":"Filter by deployment ID (deployments.id)"},"end_time":{"type":["string","null"],"description":"End of time range (ISO 8601). Defaults to now."},"envs":{"type":"array","items":{"type":"string"},"description":"Filter by environments"},"external_service_id":{"type":["integer","null"],"format":"int32","description":"When set, search an imported/managed external service's logs instead\nof a project's. `project_id` is ignored in this mode."},"levels":{"type":"array","items":{"type":"string"},"description":"Filter by log levels"},"node_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"Filter to specific worker nodes (node_id). Empty = all nodes, including\ncontrol-plane-local logs."},"page_size":{"type":["integer","null"],"format":"int32","description":"Page size (default: 100, max: 500)","minimum":0},"project_id":{"type":"integer","format":"int32","description":"Project ID (integer, as used by the rest of the platform)"},"services":{"type":"array","items":{"type":"string"},"description":"Filter by services"},"start_time":{"type":["string","null"],"description":"Start of time range (ISO 8601). Defaults to 1 hour ago."},"text":{"type":["string","null"],"description":"Full text search query"}}},"SearchLogsResponse":{"type":"object","required":["lines","search_mode","total_scanned"],"properties":{"available_sources":{"type":"array","items":{"$ref":"#/components/schemas/LogSource"},"description":"Distinct containers/nodes/services available in the queried scope, for\nthe filter dropdowns. Populated on the first page (no cursor)."},"lines":{"type":"array","items":{"$ref":"#/components/schemas/LogSearchLine"}},"next_cursor":{"type":["string","null"]},"search_mode":{"$ref":"#/components/schemas/SearchMode"},"total_scanned":{"type":"integer","format":"int64","minimum":0}}},"SearchMode":{"type":"string","description":"Search execution mode","enum":["index","archive"]},"Seasonality":{"type":"string","description":"Seasonality model for an anomaly baseline.","enum":["none","hourly","daily","weekly"]},"SecretResponse":{"type":"object","required":["id","name","secret_type","value","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mount_path":{"type":["string","null"]},"name":{"type":"string"},"secret_type":{"type":"string"},"updated_at":{"type":"string"},"value":{"type":"string","description":"Always masked in responses"}}},"SecurityConfig":{"type":"object","description":"Security configuration for projects and environments\n\nThis configuration can be set at three levels:\n1. Global (in settings table) - applies to all projects\n2. Project level - overrides global settings for specific project\n3. Environment level - overrides project settings for specific environment\n\nThe inheritance chain: Environment > Project > Global","properties":{"attackMode":{"type":["string","null"],"description":"Attack mode configuration (future: \"off\", \"challenge\", \"block\")\nPlaceholder for DDoS protection, bot detection, etc."},"challengeConfig":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeConfig","description":"Challenge configuration (future: CAPTCHA, JS challenge, etc.)"}]},"enabled":{"type":["boolean","null"],"description":"Enable/disable security features at this level\nIf None, inherits from parent level"},"geoRestrictions":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GeoRestrictionsConfig","description":"Geographic restrictions (future: country blocking, etc.)"}]},"headers":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityHeadersConfig","description":"Security headers configuration"}]},"passwordProtection":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PasswordProtectionConfig","description":"Password protection: shows an HTML password form before allowing access"}]},"rateLimiting":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RateLimitConfig","description":"Rate limiting configuration"}]}}},"SecurityHeadersConfig":{"type":"object","description":"Security headers configuration (subset of global SecurityHeadersSettings)","properties":{"contentSecurityPolicy":{"type":["string","null"],"description":"Custom CSP (only used if preset is \"custom\")"},"preset":{"type":["string","null"],"description":"Use a preset: \"strict\", \"moderate\", \"permissive\", \"disabled\", \"custom\""},"referrerPolicy":{"type":["string","null"],"description":"Referrer-Policy override"},"strictTransportSecurity":{"type":["string","null"],"description":"HSTS override"},"xFrameOptions":{"type":["string","null"],"description":"X-Frame-Options override"}}},"SecurityHeadersSettings":{"type":"object","properties":{"content_security_policy":{"type":["string","null"],"default":"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'"},"enabled":{"type":"boolean","default":false},"permissions_policy":{"type":["string","null"],"default":"geolocation=(), microphone=(), camera=()"},"preset":{"type":"string","default":"moderate"},"referrer_policy":{"type":"string","default":"strict-origin-when-cross-origin"},"strict_transport_security":{"type":"string","default":"max-age=31536000; includeSubDomains"},"x_content_type_options":{"type":"string","default":"nosniff"},"x_frame_options":{"type":"string","default":"SAMEORIGIN"},"x_xss_protection":{"type":"string","default":"1; mode=block"}}},"SendEmailRequestBody":{"type":"object","required":["from","to","subject"],"properties":{"bcc":{"type":["array","null"],"items":{"type":"string"},"description":"BCC recipients"},"cc":{"type":["array","null"],"items":{"type":"string"},"description":"CC recipients"},"from":{"type":"string","description":"Sender email address (domain will be auto-extracted for lookup)","example":"hello@updates.example.com"},"from_name":{"type":["string","null"],"description":"Sender display name","example":"My App"},"headers":{"type":["object","null"],"description":"Custom headers","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"html":{"type":["string","null"],"description":"HTML body content","example":"

Hello World

"},"reply_to":{"type":["string","null"],"description":"Reply-to address"},"subject":{"type":"string","description":"Email subject","example":"Welcome to our platform!"},"tags":{"type":["array","null"],"items":{"type":"string"},"description":"Tags for categorization","example":["welcome","onboarding"]},"text":{"type":["string","null"],"description":"Plain text body content","example":"Hello World"},"to":{"type":"array","items":{"type":"string"},"description":"Recipient email addresses","example":["user@example.com"]},"track_clicks":{"type":["boolean","null"],"description":"Enable click tracking (link rewriting). Defaults to false."},"track_opens":{"type":["boolean","null"],"description":"Enable open tracking (tracking pixel injection). Defaults to false."}}},"SendEmailResponseBody":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","description":"Email ID","example":"550e8400-e29b-41d4-a716-446655440000"},"provider_message_id":{"type":["string","null"],"description":"Provider message ID"},"status":{"type":"string","description":"Email status","example":"sent"}}},"SendMessageRequest":{"type":"object","required":["content"],"properties":{"content":{"type":"string"},"page_context":{"type":["string","null"],"description":"Optional, client-supplied description of the page/entity the user is\ncurrently viewing (e.g. a trace in a project). Injected into the model's\nview of this turn only — never stored or shown in history. Capped server\nside; oversized values are ignored rather than rejected."}}},"SensitiveConfigValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SensitiveMcpConfigValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SensitiveValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SentryChunkUploadResponse":{"type":"object","required":["url","chunkSize","chunksPerRequest","maxFileSize","maxRequestSize","concurrency","hashAlgorithm","compression","accept"],"properties":{"accept":{"type":"array","items":{"type":"string"}},"chunkSize":{"type":"integer","format":"int64","minimum":0},"chunksPerRequest":{"type":"integer","format":"int32","minimum":0},"compression":{"type":"array","items":{"type":"string"}},"concurrency":{"type":"integer","format":"int32","minimum":0},"hashAlgorithm":{"type":"string"},"maxFileSize":{"type":"integer","format":"int64","minimum":0},"maxRequestSize":{"type":"integer","format":"int64","minimum":0},"url":{"type":"string"}}},"SentryCreateReleaseRequest":{"type":"object","required":["version"],"properties":{"projects":{"type":"array","items":{"type":"string"},"description":"Project slugs this release belongs to"},"version":{"type":"string","description":"Release version identifier"}}},"SentryEventRequest":{"type":"object","properties":{"event_id":{"type":["string","null"]},"message":{"type":["string","null"]},"platform":{"type":["string","null"]},"timestamp":{"type":["string","null"]}}},"SentryEventResponse":{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}},"SentryReleaseFileResponse":{"type":"object","required":["id","name","headers","size","sha1","dateCreated"],"properties":{"dateCreated":{"type":"string"},"dist":{"type":["string","null"]},"headers":{},"id":{"type":"string"},"name":{"type":"string"},"sha1":{"type":"string"},"size":{"type":"integer","format":"int64"}}},"SentryReleaseProjectRef":{"type":"object","required":["name","slug"],"properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"SentryReleaseResponse":{"type":"object","required":["version","dateCreated","shortVersion","projects"],"properties":{"dateCreated":{"type":"string"},"dateReleased":{"type":["string","null"]},"projects":{"type":"array","items":{"$ref":"#/components/schemas/SentryReleaseProjectRef"}},"shortVersion":{"type":"string"},"version":{"type":"string"}}},"SeriesStateEntry":{"type":"object","description":"One series' persisted state snapshot for a dynamic rule (ADR-026 follow-up):\nthe state after the latest tick, the value evaluated this tick, and the open\nalarm id (when firing). Serialized into the `series_states` jsonb column keyed\nby the human-readable [`series_label`]; the alert response decodes it back.","required":["state","value"],"properties":{"alarm_id":{"type":["integer","null"],"format":"int32","description":"The open alarm's id when the series is firing; `null` when ok."},"state":{"type":"string","description":"`firing` or `ok` for this series after the latest tick."},"value":{"type":"number","format":"double","description":"The value the rule evaluated for this series this tick."}}},"ServiceAccessInfo":{"type":"object","description":"Response containing information about how the service is being accessed","required":["access_mode","can_create_domains"],"properties":{"access_mode":{"type":"string","description":"Mode of access: \"local\", \"direct\", \"nat\", or \"cloudflare_tunnel\""},"can_create_domains":{"type":"boolean","description":"Whether domain creation is allowed in this mode"},"domain_creation_error":{"type":["string","null"],"description":"Error message if domain creation is not allowed"},"private_ip":{"type":["string","null"],"description":"Server's private/local IP address (always returned if available)"},"public_ip":{"type":["string","null"],"description":"Server's public IP address (always returned if available)"}}},"ServiceAction":{"type":"string","description":"What to do with a service during migration","enum":["create","link-external","skip"]},"ServiceAlertRuleResponse":{"type":"object","description":"Wire representation of a monitoring alert rule.\n\nRegistered under a domain-prefixed OpenAPI schema name to avoid colliding\nwith `temps-error-tracking`'s unrelated `AlertRuleResponse` (utoipa keys\nschemas by their bare struct name, so without `as = ...` the last crate to\nregister would silently shadow this one in the merged spec / generated SDK).","required":["id","name","metric_name","threshold","comparator","severity","for_duration_secs","enabled"],"properties":{"comparator":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"metric_name":{"type":"string"},"name":{"type":"string"},"service_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"silenced_until":{"type":["string","null"]},"threshold":{"type":"number","format":"double"}}},"ServiceBackupEntryResponse":{"type":"object","description":"A single backup entry in the per-service backup list.","required":["id","backup_id","name","state","backup_type","started_at","s3_location","compression_type","s3_source_id","s3_source_name","external_service_backup_id"],"properties":{"backup_id":{"type":"string","description":"UUID string assigned at backup creation time."},"backup_type":{"type":"string","description":"Backup variant (e.g. \"full\", \"incremental\")."},"compression_type":{"type":"string","description":"Compression algorithm used (e.g. \"gzip\")."},"error_message":{"type":["string","null"],"description":"Engine-reported error message, populated when `state = \"failed\"`."},"external_service_backup_id":{"type":"integer","format":"int32","description":"Row ID from `external_service_backups`."},"finished_at":{"type":["string","null"],"description":"ISO 8601 timestamp when the backup finished, if known.","example":"2025-01-15T14:35:00Z"},"id":{"type":"integer","format":"int32","description":"Row ID from the `backups` table."},"name":{"type":"string","description":"Human-friendly display name."},"s3_location":{"type":"string","description":"Object key or `s3://` URL for the backup data."},"s3_source_id":{"type":"integer","format":"int32","description":"FK to `s3_sources.id`."},"s3_source_name":{"type":"string","description":"Human-readable name of the S3 source."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the backup in bytes, if available."},"started_at":{"type":"string","description":"ISO 8601 timestamp when the backup started.","example":"2025-01-15T14:30:00Z"},"state":{"type":"string","description":"Current state: \"completed\", \"running\", \"failed\"."}}},"ServiceBackupListResponse":{"type":"object","description":"Paginated list of backups for a specific external service.\n\nReturned by `GET /backups/external-services/{service_id}/backups`.","required":["backups","total","page","page_size"],"properties":{"backups":{"type":"array","items":{"$ref":"#/components/schemas/ServiceBackupEntryResponse"},"description":"Backups belonging to this service, newest first."},"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page."},"total":{"type":"integer","format":"int64","description":"Total number of backups for this service across all pages."}}},"ServiceCreateAlertRuleRequest":{"type":"object","description":"Request body for creating an alert rule on an external service.\n\nDomain-prefixed schema name — see [`AlertRuleResponse`] for why.","required":["name","metric_name","threshold","comparator","severity"],"properties":{"comparator":{"type":"string","description":"One of `>`, `<`, `>=`, `<=`."},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32","description":"Seconds the breach must persist before the alarm fires (0 = immediate)."},"metric_name":{"type":"string"},"name":{"type":"string"},"severity":{"type":"string","description":"`\"warning\"` or `\"critical\"`."},"threshold":{"type":"number","format":"double"}}},"ServiceHealthResponse":{"type":"object","required":["service_id","consecutive_failures","recent_checks"],"properties":{"consecutive_failures":{"type":"integer","format":"int32","description":"Consecutive failed probes. Alert fires at 3."},"last_checked_at":{"type":["string","null"]},"last_error":{"type":["string","null"]},"recent_checks":{"type":"array","items":{"$ref":"#/components/schemas/HealthCheckEntryResponse"},"description":"Most recent checks, newest-first (capped at `limit`)."},"response_time_ms":{"type":["integer","null"],"format":"int32"},"service_id":{"type":"integer","format":"int32"},"status":{"type":["string","null"],"description":"Current health. `null` if the service has not been probed yet.","example":"operational"},"uptime_24h_percent":{"type":["number","null"],"format":"double","description":"Uptime percentage over the last 24 hours (0.0 — 100.0).\n`null` when there is not enough history."}}},"ServiceHealthStatusBatchResponse":{"type":"object","required":["statuses"],"properties":{"statuses":{"type":"array","items":{"$ref":"#/components/schemas/ServiceHealthStatusEntryResponse"}}}},"ServiceHealthStatusEntryResponse":{"type":"object","required":["service_id","consecutive_failures"],"properties":{"consecutive_failures":{"type":"integer","format":"int32"},"last_checked_at":{"type":["string","null"]},"service_id":{"type":"integer","format":"int32"},"status":{"type":["string","null"],"description":"\"operational\" | \"degraded\" | \"down\". `null` when the service has not\nbeen probed yet.","example":"operational"}}},"ServiceMemberInfo":{"type":"object","description":"Public info about a cluster member.","required":["id","role","container_name","status","ordinal"],"properties":{"compute_ip":{"type":["string","null"],"description":"Container's IP on the `temps-overlay` multi-host network. Populated\nby the lifecycle hook (ADR-011 Phase 3); `None` on single-host\nclusters where the overlay isn't attached."},"container_name":{"type":"string"},"hostname":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"live_state":{"type":["string","null"],"description":"Live FSM state from the pg_auto_failover monitor (`primary`,\n`secondary`, `catchingup`, `report_lsn`, …). `None` when the\nmonitor is unreachable, the service is not a cluster, or the row\nis the monitor itself.\n\n**The UI must render the role badge from this field**, falling\nback to `role` only when `live_state` is null. `role` is now\nconfig-only (`monitor` or `replica`); flipping the badge to\n\"primary\" when the monitor elects a new one used to require a\nreconciler that lagged ~5s behind real failovers — and during\nthat window the UI showed two primaries. `live_state` is read\ndirectly from the monitor on every list, so it can never lag."},"node_id":{"type":["integer","null"],"format":"int32"},"ordinal":{"type":"integer","format":"int32"},"port":{"type":["integer","null"],"format":"int32"},"provisioning_error":{"type":["string","null"],"description":"Most recent provisioning failure message, when `status='failed'`.\nSet by the background task so the UI can show *why* the new\nreplica didn't come up."},"provisioning_step":{"type":["string","null"],"description":"Last-attempted phase of the async `add_cluster_member` background\ntask (e.g. `validating`, `provisioning_container`, `done`,\n`failed`). `None` for members not created through that flow —\nthe UI falls back to the `status` column for those."},"role":{"type":"string"},"status":{"type":"string"}}},"ServiceParameter":{"type":"object","required":["name","required","encrypted","description"],"properties":{"choices":{"type":["array","null"],"items":{"type":"string"}},"default_value":{"type":["string","null"]},"description":{"type":"string"},"encrypted":{"type":"boolean"},"name":{"type":"string"},"required":{"type":"boolean"},"validation_pattern":{"type":["string","null"]}}},"ServicePlan":{"type":"object","description":"Plan for migrating a single service (database, cache, etc.)","required":["name","service_type","action","action_description"],"properties":{"action":{"$ref":"#/components/schemas/ServiceAction","description":"What to do with this service"},"action_description":{"type":"string","description":"Human-readable explanation of what this action means"},"data_implications":{"type":"array","items":{"$ref":"#/components/schemas/DataImplication"},"description":"Data implications specific to this service"},"env_var_mappings":{"type":"object","description":"Environment variable key mappings: source_key -> temps_key\n\nFor example, Vercel's `POSTGRES_URL` might map to Temps' `DATABASE_URL`.\nBoth keys will be set during migration so the app works with either.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Human-readable service name"},"parameters":{"type":"object","description":"Parameters for creating the service in Temps","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"type":"string","description":"Service type (maps to temps-providers ServiceType)"},"version":{"type":["string","null"],"description":"Service version to create (e.g., \"16\" for Postgres 16)"}}},"ServiceResourceLimits":{"type":"object","description":"Optional cgroup resource limits applied to a service container.\n\nAll fields are `Option`: `None` means \"no limit\" (the kernel default),\nmatching Docker's behavior when the corresponding `HostConfig` field is\nleft at zero. Operators opt in to limits explicitly through the\n`PATCH /external-services/{id}/resources` endpoint or by writing the\n`resources` block into `ServiceConfig::parameters` at create time.\n\nThese map directly onto bollard fields:\n- `memory_mb` → `HostConfig.memory` (bytes)\n- `memory_swap_mb`→ `HostConfig.memory_swap` (bytes; ≥ memory)\n- `nano_cpus` → `HostConfig.nano_cpus` (1e9 = 1 full CPU)\n- `cpu_shares` → `HostConfig.cpu_shares` (relative weight, default 1024)\n- `shm_size_mb` → `HostConfig.shm_size` (bytes; default 64 MiB)\n\nIMPORTANT: enabling hard memory limits causes the kernel OOM killer to\nterminate the container when the working set exceeds the limit. The\ncontainer will restart (RestartPolicy::ALWAYS) but in-flight queries\nfail. Surface this clearly in any UI that lets users set limits.","properties":{"cpu_shares":{"type":["integer","null"],"format":"int64","description":"Relative CPU weight (default 1024). Only used when `nano_cpus` is None."},"memory_mb":{"type":["integer","null"],"format":"int64","description":"Hard memory limit in MiB. None = unlimited."},"memory_swap_mb":{"type":["integer","null"],"format":"int64","description":"Memory + swap limit in MiB. None = unlimited.\nMUST be >= memory_mb when both are set; Docker rejects the request otherwise.\nSet equal to `memory_mb` to disable swap entirely."},"nano_cpus":{"type":["integer","null"],"format":"int64","description":"CPU quota in nano-cpus. 1_000_000_000 = 1 full CPU core. None = unlimited."},"shm_size_mb":{"type":["integer","null"],"format":"int64","description":"Shared memory (/dev/shm) size in MiB. None = Docker default (64 MiB).\nMaps to HostConfig.shm_size (bytes). PostgreSQL uses /dev/shm for parallel\nquery workers and large work_mem; the 64 MiB default causes \"could not\nresize shared memory segment ... No space left on device\" under load.\nNOTE: shm_size is fixed at container-create time — Docker's live update\nAPI cannot change it, so changing this value recreates the container."}}},"ServiceRuntimeReport":{"type":"object","description":"Aggregate runtime info for an external service. For standalone services,\n`members` has exactly one entry. For clusters, one entry per member.","required":["service_id","topology","members"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ContainerRuntimeInfo"}},"service_id":{"type":"integer","format":"int32"},"topology":{"type":"string"}}},"ServiceStatsReport":{"type":"object","required":["service_id","topology","members"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ContainerStatsSample"}},"service_id":{"type":"integer","format":"int32"},"topology":{"type":"string"}}},"ServiceTypeInfo":{"type":"object","required":["service_type","parameters"],"properties":{"parameters":{"type":"array","items":{"$ref":"#/components/schemas/ServiceParameter"},"example":"[{\"name\": \"host\", \"required\": true, \"encrypted\": false, \"description\": \"Database host\"}]"},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"}}},"ServiceTypeRoute":{"type":"string","enum":["mariadb","mongodb","postgres","redis","s3","kv","blob","rustfs","minio"]},"ServiceUpdateAlertRuleRequest":{"type":"object","description":"Request body for updating an existing alert rule.\n\nDomain-prefixed schema name — see [`AlertRuleResponse`] for why.","properties":{"comparator":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"for_duration_secs":{"type":["integer","null"],"format":"int32"},"metric_name":{"type":["string","null"]},"name":{"type":["string","null"]},"severity":{"type":["string","null"]},"threshold":{"type":["number","null"],"format":"double"}}},"SesCredentialsRequest":{"type":"object","required":["access_key_id","secret_access_key"],"properties":{"access_key_id":{"type":"string","example":"AKIAIOSFODNN7EXAMPLE"},"secret_access_key":{"type":"string","example":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"}}},"SessionDetails":{"type":"object","required":["session_id","visitor_id","started_at","duration_seconds","is_bounced","is_engaged","page_views"],"properties":{"duration_seconds":{"type":"integer","format":"int64"},"ended_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00"},"entry_path":{"type":["string","null"]},"exit_path":{"type":["string","null"]},"is_bounced":{"type":"boolean"},"is_engaged":{"type":"boolean"},"page_views":{"type":"integer","format":"int64"},"referrer":{"type":["string","null"]},"session_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"visitor_id":{"type":"string"}}},"SessionDetailsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"SessionEvent":{"type":"object","required":["id","timestamp"],"properties":{"event_data":{},"event_name":{"type":["string","null"]},"event_type":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"page_title":{"type":["string","null"]},"page_url":{"type":["string","null"]},"timestamp":{"type":"string"}}},"SessionEventDto":{"type":"object","required":["id","session_id","data","timestamp"],"properties":{"data":{},"event_type":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"timestamp":{"type":"integer","format":"int64"}}},"SessionEventsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"SessionEventsResponse":{"type":"object","required":["session_id","events","total_count","offset","limit"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEvent"}},"limit":{"type":"integer","format":"int32"},"offset":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"total_count":{"type":"integer","format":"int64"}}},"SessionLogsQuery":{"type":"object","required":["project_id"],"properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"offset":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"sort_order":{"type":["string","null"]},"start_date":{"type":["string","null"],"format":"date-time"},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"SessionLogsResponse":{"type":"object","required":["session_id","logs","total_count","offset","limit"],"properties":{"limit":{"type":"integer","format":"int32"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/SessionRequestLog"}},"offset":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"total_count":{"type":"integer","format":"int64"}}},"SessionReplayEventsRequest":{"type":"object","required":["sessionId","events"],"properties":{"events":{"type":"string"},"sessionId":{"type":"string"}}},"SessionReplayInfoDto":{"type":"object","required":["id","visitor_id"],"properties":{"created_at":{"type":["string","null"]},"duration":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"language":{"type":["string","null"]},"screen_height":{"type":["integer","null"],"format":"int32"},"screen_width":{"type":["integer","null"],"format":"int32"},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"viewport_height":{"type":["integer","null"],"format":"int32"},"viewport_width":{"type":["integer","null"],"format":"int32"},"visitor_id":{"type":"integer","format":"int32"}}},"SessionReplayInitRequest":{"type":"object","required":["sessionId"],"properties":{"colorDepth":{"type":["integer","null"],"format":"int32","minimum":0},"language":{"type":["string","null"]},"screenHeight":{"type":["integer","null"],"format":"int32","minimum":0},"screenWidth":{"type":["integer","null"],"format":"int32","minimum":0},"sessionId":{"type":"string"},"timestamp":{"type":["string","null"]},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"userAgent":{"type":["string","null"]},"viewportHeight":{"type":["integer","null"],"format":"int32","minimum":0},"viewportWidth":{"type":["integer","null"],"format":"int32","minimum":0}}},"SessionReplayInitResponse":{"type":"object","required":["session_id","message"],"properties":{"message":{"type":"string"},"session_id":{"type":"string"}}},"SessionReplayWithEventsDto":{"type":"object","required":["session","events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEventDto"}},"session":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}}},"SessionReplayWithVisitorDto":{"type":"object","required":["id","session_replay_id","visitor_id","visitor_uuid","visitor_project_id","visitor_environment_id","visitor_first_seen","visitor_last_seen","visitor_is_crawler"],"properties":{"browser":{"type":["string","null"]},"browser_version":{"type":["string","null"]},"created_at":{"type":["string","null"]},"device_type":{"type":["string","null"]},"duration":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"language":{"type":["string","null"]},"operating_system":{"type":["string","null"]},"operating_system_version":{"type":["string","null"]},"screen_height":{"type":["integer","null"],"format":"int32"},"screen_width":{"type":["integer","null"],"format":"int32"},"session_replay_id":{"type":"string"},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"viewport_height":{"type":["integer","null"],"format":"int32"},"viewport_width":{"type":["integer","null"],"format":"int32"},"visitor_city":{"type":["string","null"]},"visitor_country":{"type":["string","null"]},"visitor_country_code":{"type":["string","null"]},"visitor_crawler_name":{"type":["string","null"]},"visitor_custom_data":{},"visitor_environment_id":{"type":"integer","format":"int32"},"visitor_first_seen":{"type":"string"},"visitor_id":{"type":"integer","format":"int32"},"visitor_is_crawler":{"type":"boolean"},"visitor_last_seen":{"type":"string"},"visitor_project_id":{"type":"integer","format":"int32"},"visitor_region":{"type":["string","null"]},"visitor_uuid":{"type":"string"}}},"SessionRequestLog":{"type":"object","required":["id","method","path","status_code","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"referrer":{"type":["string","null"]},"request_headers":{"type":["string","null"]},"response_headers":{"type":["string","null"]},"response_time_ms":{"type":["integer","null"],"format":"int32"},"status_code":{"type":"integer","format":"int32"},"user_agent":{"type":["string","null"]}}},"SessionSummary":{"type":"object","required":["session_id","started_at","duration_seconds","page_views","events_count","requests_count","is_bounced","is_engaged"],"properties":{"duration_seconds":{"type":"integer","format":"int64"},"ended_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00"},"entry_path":{"type":["string","null"]},"events_count":{"type":"integer","format":"int64"},"exit_path":{"type":["string","null"]},"is_bounced":{"type":"boolean"},"is_engaged":{"type":"boolean"},"page_views":{"type":"integer","format":"int64"},"referrer":{"type":["string","null"]},"requests_count":{"type":"integer","format":"int64"},"session_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"}}},"SetFlagEnvironmentRequest":{"type":"object","properties":{"enabled":{"type":["boolean","null"],"description":"The kill switch. `false` makes the flag serve its default regardless of\nany override — and, once targeting exists, regardless of any rule."},"value":{"description":"Tri-state: absent leaves the override, `null` clears it (inherit the\nflag default), anything else sets it. Must match `value_type`."}}},"SetPreviewPasswordBody":{"type":"object","required":["password"],"properties":{"password":{"type":"string","description":"Plaintext password to protect the sandbox's preview URLs. Hashed\nserver-side with argon2id — we never persist or echo this back.\nMust be between 8 and 256 characters."}}},"SetPreviewPasswordResponse":{"type":"object","required":["preview_password_hint"],"properties":{"preview_password_hint":{"type":"string","description":"Last 4 chars of the password we just stored. Surface in the UI so\nusers can confirm which password is live without re-entering it."}}},"SetRequest":{"type":"object","description":"Request to set a value","required":["key","value"],"properties":{"ex":{"type":["integer","null"],"format":"int64","description":"Expire in seconds","example":3600},"key":{"type":"string","description":"The key to set","example":"user:123"},"nx":{"type":"boolean","description":"Only set if key does not exist"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"px":{"type":["integer","null"],"format":"int64","description":"Expire in milliseconds"},"value":{"description":"The value to store (can be any JSON value)"},"xx":{"type":"boolean","description":"Only set if key exists"}}},"SetResponse":{"type":"object","description":"Response for set operation","required":["result"],"properties":{"result":{"type":"string","description":"Always \"OK\" on success","example":"OK"}}},"SettingsUpdateResponse":{"type":"object","description":"Response for successful settings update","required":["message"],"properties":{"message":{"type":"string"}}},"SetupDnsChallengeRequest":{"type":"object","description":"Request to setup DNS challenge records using a configured DNS provider","required":["dns_provider_id"],"properties":{"dns_provider_id":{"type":"integer","format":"int32","description":"The ID of the DNS provider to use for creating the TXT records"}}},"SetupDnsChallengeResponse":{"type":"object","description":"Response from DNS challenge setup operation","required":["success","records_created","total_records","results","message"],"properties":{"message":{"type":"string","description":"Human-readable summary message"},"records_created":{"type":"integer","format":"int32","description":"Number of TXT records that were successfully created","minimum":0},"results":{"type":"array","items":{"$ref":"#/components/schemas/DnsChallengeRecordResult"},"description":"Results for each individual TXT record"},"success":{"type":"boolean","description":"Overall success status (true if all records were created)"},"total_records":{"type":"integer","format":"int32","description":"Total number of TXT records required for the challenge","minimum":0}}},"SetupDnsRequest":{"type":"object","description":"Request to setup DNS records using a configured DNS provider","required":["dns_provider_id"],"properties":{"dns_provider_id":{"type":"integer","format":"int32","description":"The ID of the DNS provider to use for creating records"}}},"SetupDnsResponse":{"type":"object","description":"Response from DNS setup operation","required":["success","records_created","total_records","results","message"],"properties":{"message":{"type":"string","description":"Human-readable summary message"},"records_created":{"type":"integer","format":"int32","description":"Number of records that were successfully created","minimum":0},"results":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordSetupResult"},"description":"Results for each individual record"},"success":{"type":"boolean","description":"Overall success status"},"total_records":{"type":"integer","format":"int32","description":"Total number of records attempted","minimum":0}}},"SiblingRef":{"type":"object","description":"A sibling project that shares the same `trace_id` and has opted in to\ncross-project trace sharing (`cross_project_trace_sharing = TRUE`).\n\nReturned by `CrossProjectTraceService::find_sibling_projects` and exposed\nby the Phase 1 `GET /otel/traces/cross-project/{trace_id}` endpoint.","required":["project_id","project_name","project_slug","first_seen"],"properties":{"first_seen":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the sibling project's single-project trace view."}}},"SkillDefinitionResponse":{"type":"object","required":["id","slug","name","content","has_archive","created_at","updated_at"],"properties":{"content":{"type":"string"},"created_at":{"type":"string"},"description":{"type":["string","null"]},"has_archive":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"SlackConfig":{"type":"object","required":["webhook_url"],"properties":{"channel":{"type":["string","null"]},"webhook_url":{"type":"string"}}},"SlowQueriesResponse":{"type":"object","description":"Response envelope for the slow-queries list endpoint.","required":["queries","page","page_size","total_count"],"properties":{"page":{"type":"integer","format":"int32","description":"Current page number (1-based).","minimum":0},"page_size":{"type":"integer","format":"int32","description":"Number of rows per page used for this request.","minimum":0},"queries":{"type":"array","items":{"$ref":"#/components/schemas/SlowQueryRow"},"description":"Ordered list of query stats, slowest first by mean_exec_time_ms."},"total_count":{"type":"integer","format":"int64","description":"Total number of qualifying rows across all pages.","minimum":0}}},"SlowQueryRow":{"type":"object","description":"A single entry from `pg_stat_statements`, representing one normalized\nquery fingerprint and its aggregate execution stats.","required":["query","database","calls","total_exec_time_ms","mean_exec_time_ms","rows"],"properties":{"cache_hit_ratio":{"type":["number","null"],"format":"double","description":"Shared block cache hit ratio (0.0–1.0).\n`None` when total block accesses are zero (e.g. function-only queries)."},"calls":{"type":"integer","format":"int64","description":"Number of times this query was executed."},"database":{"type":"string","description":"Name of the database this query ran against. `(dropped database)`\nwhen the originating database no longer exists but\n`pg_stat_statements` still holds stats for it."},"mean_exec_time_ms":{"type":"number","format":"double","description":"Average wall-clock time per execution, in milliseconds."},"query":{"type":"string","description":"Normalized query text (parameter literals replaced with `$N`)."},"rows":{"type":"integer","format":"int64","description":"Total number of rows returned or affected."},"total_exec_time_ms":{"type":"number","format":"double","description":"Total wall-clock time spent executing this query, in milliseconds."}}},"SmartFilter":{"oneOf":[{"type":"object","description":"Match specific page path","required":["value","type"],"properties":{"type":{"type":"string","enum":["page_path"]},"value":{"type":"string","description":"Match specific page path"}}},{"type":"object","description":"Match specific hostname","required":["value","type"],"properties":{"type":{"type":"string","enum":["hostname"]},"value":{"type":"string","description":"Match specific hostname"}}},{"type":"object","description":"Match UTM source","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_source"]},"value":{"type":"string","description":"Match UTM source"}}},{"type":"object","description":"Match UTM campaign","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_campaign"]},"value":{"type":"string","description":"Match UTM campaign"}}},{"type":"object","description":"Match UTM medium","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_medium"]},"value":{"type":"string","description":"Match UTM medium"}}},{"type":"object","description":"Match referrer hostname","required":["value","type"],"properties":{"type":{"type":"string","enum":["referrer_hostname"]},"value":{"type":"string","description":"Match referrer hostname"}}},{"type":"object","description":"Match specific channel (organic, paid, direct, referral, etc.)","required":["value","type"],"properties":{"type":{"type":"string","enum":["channel"]},"value":{"type":"string","description":"Match specific channel (organic, paid, direct, referral, etc.)"}}},{"type":"object","description":"Match device type (mobile, desktop, tablet)","required":["value","type"],"properties":{"type":{"type":"string","enum":["device_type"]},"value":{"type":"string","description":"Match device type (mobile, desktop, tablet)"}}},{"type":"object","description":"Match browser","required":["value","type"],"properties":{"type":{"type":"string","enum":["browser"]},"value":{"type":"string","description":"Match browser"}}},{"type":"object","description":"Match operating system","required":["value","type"],"properties":{"type":{"type":"string","enum":["operating_system"]},"value":{"type":"string","description":"Match operating system"}}},{"type":"object","description":"Match language","required":["value","type"],"properties":{"type":{"type":"string","enum":["language"]},"value":{"type":"string","description":"Match language"}}},{"type":"object","description":"Match custom event_data by JSON path\nFormat: {\"path\": \"user.plan\", \"value\": \"premium\"}\nThis will match events where event_data->'user'->>'plan' = 'premium'","required":["value","type"],"properties":{"type":{"type":"string","enum":["custom_data"]},"value":{"type":"object","description":"Match custom event_data by JSON path\nFormat: {\"path\": \"user.plan\", \"value\": \"premium\"}\nThis will match events where event_data->'user'->>'plan' = 'premium'","required":["path","value"],"properties":{"path":{"type":"string"},"value":{"type":"string"}}}}}],"description":"Smart filter presets for common funnel patterns"},"SmokeTestResponse":{"type":"object","required":["passed","environment","cli_installed","cli_authenticated"],"properties":{"auth_info":{"type":["string","null"],"description":"Auth email / method"},"cli_authenticated":{"type":"boolean","description":"Claude CLI authenticated?"},"cli_installed":{"type":"boolean","description":"Claude CLI installed?"},"cli_version":{"type":["string","null"],"description":"Claude CLI version"},"detail":{"type":["string","null"],"description":"Full output for debugging"},"environment":{"type":"string","description":"Where the test ran: \"host\" or \"sandbox\""},"passed":{"type":"boolean","description":"Whether the smoke test passed"},"setup_hint":{"type":["string","null"],"description":"What the user needs to do if the test failed"}}},"SmtpCredentialsRequest":{"type":"object","description":"Generic SMTP credentials request body.\n\nWorks with any SMTP relay — AWS SES SMTP endpoints, Sendgrid, Mailgun,\nPostmark, or a self-hosted Postfix. Use this when you only have SMTP\ncredentials (i.e. you cannot create identities via the upstream API).","required":["host","port"],"properties":{"accept_invalid_certs":{"type":"boolean","description":"Accept self-signed certificates. Only safe for local testing."},"encryption":{"$ref":"#/components/schemas/SmtpEncryptionRoute","description":"TLS mode. Defaults to STARTTLS."},"host":{"type":"string","description":"SMTP host, e.g. `email-smtp.eu-west-1.amazonaws.com`.","example":"email-smtp.eu-west-1.amazonaws.com"},"password":{"type":["string","null"],"description":"SMTP password / API token. Required when `username` is set."},"port":{"type":"integer","format":"int32","description":"SMTP port (587 for STARTTLS, 465 for implicit TLS, 25/1025 for plain).","example":587,"minimum":0},"username":{"type":["string","null"],"description":"SMTP username. Leave empty for unauthenticated relays.","example":"AKIAIOSFODNN7EXAMPLE"}}},"SmtpEncryptionRoute":{"type":"string","description":"TLS mode for the SMTP relay.","enum":["starttls","tls","none"]},"SmtpResult":{"type":"object","description":"SMTP validation result","required":["can_connect_smtp","has_full_inbox","is_catch_all","is_deliverable","is_disabled"],"properties":{"can_connect_smtp":{"type":"boolean","description":"Whether we could connect to the SMTP server"},"error":{"type":["string","null"],"description":"Error message if SMTP check failed"},"has_full_inbox":{"type":"boolean","description":"Whether the mailbox appears to have a full inbox"},"is_catch_all":{"type":"boolean","description":"Whether this is a catch-all domain"},"is_deliverable":{"type":"boolean","description":"Whether the email is deliverable"},"is_disabled":{"type":"boolean","description":"Whether the mailbox is disabled"}}},"SourceBackupEntry":{"type":"object","description":"Entry in the source backup index. Covers both DB-tracked backups\n(have a row in `backups`) and S3-scan discoveries (raw S3 objects with\nno DB row — used for disaster-recovery from another Temps instance).","required":["id","backup_id","name","backup_type","created_at","location","metadata_location","source","state"],"properties":{"backup_id":{"type":"string","description":"UUID identifier from the DB row. Empty for S3-scan entries.","example":"550e8400-e29b-41d4-a716-446655440000"},"backup_type":{"type":"string","description":"Backup variant as recorded by the backup pipeline (e.g. \"full\").","example":"full"},"created_at":{"type":"string","description":"When the backup was created. For S3-scan entries this is the\nobject's LastModified time.","example":"2024-01-15T14:30:00.123Z"},"engine":{"type":["string","null"],"description":"Engine that produced the backup (\"postgres\", \"redis\", \"mongodb\",\n\"s3\", \"rustfs\"). Used by the UI to mark engine-compat with the\ntarget service.","example":"postgres"},"format":{"type":["string","null"],"description":"Storage format: \"walg\" for continuous-archive (PITR-capable),\n\"pg_dump\" for point-in-time dumps, \"\" for non-postgres.","example":"walg"},"id":{"type":"integer","format":"int32","description":"DB row id. Zero for S3-scan entries that have no DB row.","example":1},"location":{"type":"string","description":"Raw S3 URL / key where the backup sits. For Postgres WAL-G backups\nthis starts with `s3://`; for pg_dump-style backups it's the\nrelative object key.","example":"s3://bucket/external_services/postgres/svc-name/walg"},"metadata_location":{"type":"string","description":"Sidecar metadata.json location, if any. Empty when none.","example":""},"name":{"type":"string","description":"Human-friendly display name (\"postgres backup (svc-name)\" for DB\nrows, or a synthesized label derived from the S3 path for scans).","example":"postgres backup (postgres-n4ea)"},"origin_service_name":{"type":["string","null"],"description":"Name of the service that produced the backup. For S3-scan entries\nthis is parsed from the S3 path.","example":"postgres-n4ea"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the backup in bytes, if known.","example":1024000},"source":{"type":"string","description":"Provenance: \"db\" for rows in this Temps, \"s3_scan\" for objects\ndiscovered by the S3 bucket walk (e.g., backups made by another\nTemps instance).","example":"db"},"state":{"type":"string","description":"Observed state (\"completed\", \"running\", \"failed\") — DB only.\nEmpty string for S3-scan entries.","example":"completed"}}},"SourceBackupIndexResponse":{"type":"object","description":"Response type for source backup index","required":["backups","last_updated"],"properties":{"backups":{"type":"array","items":{"$ref":"#/components/schemas/SourceBackupEntry"},"description":"List of backups in the source"},"last_updated":{"type":"string","description":"When the index was last updated","example":"2024-01-15T14:30:00.123Z"}}},"SourceBody":{"oneOf":[{"type":"object","required":["url","type"],"properties":{"depth":{"type":["integer","null"],"format":"int32","minimum":0},"git_connection_id":{"type":["integer","null"],"format":"int32"},"password":{"type":["string","null"]},"revision":{"type":["string","null"]},"type":{"type":"string","enum":["git"]},"url":{"type":"string"},"username":{"type":["string","null"]}}},{"type":"object","required":["url","type"],"properties":{"type":{"type":"string","enum":["tarball"]},"url":{"type":"string"}}}],"description":"Initial content to seed into the sandbox work dir. Mirrors the\n`@vercel/sandbox` `source` option. `type` is one of:\n- `git` — clone `url`; optionally check out `revision`\n- `tarball` — download `url` (must be tar or tar.gz) and extract\n\nFor private git repos, pass credentials one of two ways:\n1. **Inline (SDK-compatible):** `username` + `password`. GitHub\n tokens use `username: \"x-access-token\"`.\n2. **Stored connection (temps-native):** `git_connection_id`\n references a row in the caller's git provider connections. Temps\n resolves the token server-side and injects it safely.\n\n`git_connection_id` is mutually exclusive with `username`/`password`."},"SourceFileListResponse":{"type":"object","required":["source_files","total"],"properties":{"source_files":{"type":"array","items":{"$ref":"#/components/schemas/SourceFileResponse"}},"total":{"type":"integer","minimum":0}}},"SourceFileResponse":{"type":"object","required":["id","project_id","release","file_path","size_bytes","created_at"],"properties":{"checksum":{"type":["string","null"]},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"file_path":{"type":"string"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"release":{"type":"string"},"size_bytes":{"type":"integer","format":"int64"}}},"SourceMapListResponse":{"type":"object","required":["source_maps","total"],"properties":{"source_maps":{"type":"array","items":{"$ref":"#/components/schemas/SourceMapResponse"}},"total":{"type":"integer","minimum":0}}},"SourceMapResponse":{"type":"object","required":["id","project_id","release","file_path","size_bytes","created_at"],"properties":{"checksum":{"type":["string","null"]},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"dist":{"type":["string","null"]},"file_path":{"type":"string"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"release":{"type":"string"},"size_bytes":{"type":"integer","format":"int64"}}},"SourceType":{"type":"string","description":"Source type for project deployments\n\nDetermines where the deployment artifacts come from:\n- `Git`: Source code from a Git repository (traditional flow)\n- `DockerImage`: Pre-built Docker image from external registry\n- `StaticFiles`: Pre-built static files uploaded as a bundle\n- `Manual`: Flexible type that accepts any deployment method","enum":["git","docker_image","static_files","manual"]},"SpanEvent":{"type":"object","description":"A span event (log-like annotation on a span).","required":["timestamp","name","attributes"],"properties":{"attributes":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"SpanKind":{"type":"string","description":"Span kind.","enum":["UNSPECIFIED","INTERNAL","SERVER","CLIENT","PRODUCER","CONSUMER"]},"SpanRecord":{"type":"object","description":"A single trace span ready for storage.","required":["project_id","resource","trace_id","span_id","name","kind","start_time","end_time","duration_ms","status_code","status_message","attributes","events"],"properties":{"attributes":{"type":"object","description":"Raw key/value pairs exactly as reported by the instrumenting library.\nNumeric values are NOT guaranteed to share `duration_ms`'s unit — they\nmay be seconds, milliseconds, microseconds, or nanoseconds depending on\nthe exporter's own convention, and the unit is not labeled here.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"deployment_id":{"type":["integer","null"],"format":"int32"},"duration_ms":{"type":"number","format":"double","description":"Span duration in milliseconds. The only field on this struct guaranteed\nto be in milliseconds."},"end_time":{"type":"string","format":"date-time"},"events":{"type":"array","items":{"$ref":"#/components/schemas/SpanEvent"}},"kind":{"$ref":"#/components/schemas/SpanKind"},"name":{"type":"string"},"parent_span_id":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"resource":{"$ref":"#/components/schemas/ResourceInfo"},"span_id":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"status_message":{"type":"string"},"trace_id":{"type":"string"}}},"SpanRow":{"type":"object","required":["id","ts","trace_id","span_id","service","operation","attributes","attributes_truncated"],"properties":{"attributes":{},"attributes_truncated":{"type":"boolean"},"deployment_id":{"type":["integer","null"],"format":"int32"},"duration_ms":{"type":["number","null"],"format":"double"},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"operation":{"type":"string"},"parent_span_id":{"type":["string","null"]},"service":{"type":"string"},"span_id":{"type":"string"},"status":{"type":["string","null"]},"trace_id":{"type":"string"},"ts":{"type":"string","format":"date-time"}}},"SpanStatusCode":{"type":"string","description":"Span status code.","enum":["UNSET","OK","ERROR"]},"SpeedMetricsPayload":{"type":"object","description":"Speed metrics payload for recording web vitals","properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"fcp":{"type":["number","null"],"format":"float","description":"First Contentful Paint (milliseconds)"},"fid":{"type":["number","null"],"format":"float","description":"First Input Delay (milliseconds)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"},"language":{"type":["string","null"],"description":"Browser language"},"lcp":{"type":["number","null"],"format":"float","description":"Largest Contentful Paint (milliseconds)"},"pathname":{"type":["string","null"],"description":"Page pathname"},"query":{"type":["string","null"],"description":"Query string"},"screenHeight":{"type":["integer","null"],"format":"int32","description":"Screen height in pixels"},"screenWidth":{"type":["integer","null"],"format":"int32","description":"Screen width in pixels"},"ttfb":{"type":["number","null"],"format":"float","description":"Time to First Byte (milliseconds)"},"viewportHeight":{"type":["integer","null"],"format":"int32","description":"Viewport height in pixels"},"viewportWidth":{"type":["integer","null"],"format":"int32","description":"Viewport width in pixels"}}},"SpeedSegmentFilters":{"type":"object","description":"Optional segment filters for the performance read endpoints, mirroring\nanalytics' `VisitorSegmentFilters`. Each filter narrows results to samples\nmatching the dimension value, so metrics can be scoped to e.g. one page,\none browser, or one country. Geographic filters resolve via\n`ip_geolocations`; the rest live directly on `performance_metrics`.","properties":{"filter_browser":{"type":["string","null"],"description":"Browser name (matches `performance_metrics.browser`)"},"filter_city":{"type":["string","null"],"description":"Geolocation city (matches `ip_geolocations.city`)"},"filter_country":{"type":["string","null"],"description":"Geolocation country (matches `ip_geolocations.country`)"},"filter_operating_system":{"type":["string","null"],"description":"Operating system (matches `performance_metrics.operating_system`)"},"filter_path":{"type":["string","null"],"description":"Page pathname (matches `performance_metrics.pathname`)"},"filter_region":{"type":["string","null"],"description":"Geolocation region (matches `ip_geolocations.region`)"}}},"StaleSlot":{"type":"object","required":["slot_name","active","retained_bytes"],"properties":{"active":{"type":"boolean"},"retained_bytes":{"type":"integer","format":"int64"},"slot_name":{"type":"string"}}},"StartAnalysisRequest":{"type":"object","required":["error_group_id"],"properties":{"branch":{"type":["string","null"],"description":"Branch to clone instead of the project's main branch."},"error_group_id":{"type":"integer","format":"int32"},"max_turns":{"type":["integer","null"],"format":"int32","description":"Per-run turn cap applied to every phase (1–200). Only enforced for\nCLIs with a turn flag (Claude Code). `None` uses the provider's\nconfigured defaults."},"model":{"type":["string","null"],"description":"Model id for the chosen provider. `None` uses the provider's saved\ndefault model."},"provider":{"type":["string","null"],"description":"AI provider id (\"claude_cli\", \"codex_cli\", \"opencode\"). `None` uses\nthe platform default provider."},"user_context":{"type":["string","null"],"description":"Free-text notes for the model (extra context about the error, retry\nguidance, constraints). Included verbatim in the analysis prompt."}}},"StartPgUpgradeRequest":{"type":"object","required":["from_version","to_version","from_image","to_image"],"properties":{"from_image":{"type":"string","example":"postgres:16-bookworm"},"from_version":{"type":"string","example":"16"},"to_image":{"type":"string","example":"postgres:17-bookworm"},"to_version":{"type":"string","example":"17"}}},"StartRestoreRequest":{"allOf":[{"$ref":"#/components/schemas/RestoreRequestMode","description":"Requested restore mode. See `RestoreRequestMode`."},{"type":"object","properties":{"backup_engine":{"type":["string","null"],"description":"Engine of the backup when specified by `backup_location`\n(\"postgres\", \"redis\", \"mongodb\", \"s3\"). Ignored when `backup_id`\nis used — we infer from the DB row."},"backup_id":{"type":["integer","null"],"format":"int32","description":"DB id of the backup to restore from. Either `backup_id` or\n`backup_location` MUST be provided. Use `backup_id` when restoring\na backup this Temps instance recorded."},"backup_location":{"type":["string","null"],"description":"Raw S3 URL / key of the backup — used when restoring a backup\ndiscovered by S3 scan (i.e., produced by another Temps instance).\nRequires `backup_engine` and `s3_source_id` to also be set."},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"S3 source the `backup_location` lives in. Ignored when `backup_id`\nis used."}}}]},"StatResponse":{"type":"object","required":["path","exists","is_dir","is_file","size"],"properties":{"exists":{"type":"boolean"},"is_dir":{"type":"boolean"},"is_file":{"type":"boolean"},"path":{"type":"string"},"size":{"type":"integer","format":"int64","minimum":0}}},"StaticBundleResponse":{"type":"object","required":["id","project_id","blob_path","content_type","size_bytes","uploaded_at","created_at"],"properties":{"blob_path":{"type":"string"},"checksum":{"type":["string","null"]},"content_type":{"type":"string"},"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"format":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"metadata":{},"original_filename":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"size_bytes":{"type":"integer","format":"int64"},"uploaded_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"}}},"StaticParams":{"type":"object","description":"Static threshold detector: compare the aggregated `value` against `threshold`.","required":["comparator","threshold"],"properties":{"comparator":{"$ref":"#/components/schemas/Comparator","description":"How `value` is compared against `threshold`."},"threshold":{"type":"number","format":"double","description":"The threshold the aggregated value is compared against."}}},"StaticPresetConfig":{"type":"object","description":"Configuration for static site presets (Vite, Next.js, Docusaurus, etc.)\nThese presets build static sites that are served via a web server","properties":{"buildCommand":{"type":["string","null"],"description":"Custom build command (overrides preset default)","example":"npm run build:production"},"buildContext":{"type":["string","null"],"description":"Custom build context path (relative to repository root)\nUseful for monorepo setups where the app is in a subdirectory","example":"./apps/frontend"},"installCommand":{"type":["string","null"],"description":"Custom install command (overrides auto-detected package manager)","example":"npm ci"},"outputDir":{"type":["string","null"],"description":"Custom output directory (overrides preset default)\nCommon values: \"dist\", \"build\", \".next\", \"out\"","example":"dist"}}},"StatsFilters":{"type":"object","description":"Filters for statistics queries","properties":{"client_ip":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"has_project":{"type":["boolean","null"],"description":"When true, only count requests that matched a project (project_id IS NOT NULL).\nUsed by the health dashboard so totals match the per-project cards."},"host":{"type":["string","null"]},"is_bot":{"type":["boolean","null"]},"method":{"type":["string","null"]},"project_id":{"type":["integer","null"],"format":"int32"},"request_source":{"type":["string","null"]},"routing_status":{"type":["string","null"]},"status_code":{"type":["integer","null"],"format":"int32"},"status_code_class":{"type":["string","null"],"description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")"}}},"StatusBucket":{"type":"object","required":["bucket_start","status","total_checks","operational_count","degraded_count","down_count","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["number","null"],"format":"double"},"bucket_start":{"type":"string","format":"date-time"},"degraded_count":{"type":"integer","format":"int64"},"down_count":{"type":"integer","format":"int64"},"max_response_time_ms":{"type":["number","null"],"format":"double"},"min_response_time_ms":{"type":["number","null"],"format":"double"},"operational_count":{"type":"integer","format":"int64"},"p50_response_time_ms":{"type":["number","null"],"format":"double"},"p95_response_time_ms":{"type":["number","null"],"format":"double"},"p99_response_time_ms":{"type":["number","null"],"format":"double"},"status":{"type":"string"},"total_checks":{"type":"integer","format":"int64"},"uptime_percentage":{"type":"number","format":"double"}}},"StatusBucketedResponse":{"type":"object","required":["monitor_id","interval","buckets"],"properties":{"buckets":{"type":"array","items":{"$ref":"#/components/schemas/StatusBucket"}},"interval":{"type":"string"},"monitor_id":{"type":"integer","format":"int32"}}},"StatusCodeCount":{"type":"object","required":["status_code","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"status_code":{"type":"integer","format":"int32"}}},"StatusCodesQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"StatusPageOverview":{"type":"object","required":["status","monitors","recent_incidents"],"properties":{"monitors":{"type":"array","items":{"$ref":"#/components/schemas/MonitorStatus"}},"recent_incidents":{"type":"array","items":{"$ref":"#/components/schemas/IncidentResponse"}},"status":{"type":"string"}}},"StepConversionResponse":{"type":"object","required":["step_id","step_name","step_order","completions","conversion_rate","drop_off_rate","average_time_to_complete_seconds"],"properties":{"average_time_to_complete_seconds":{"type":"number","format":"double"},"completions":{"type":"integer","format":"int64","minimum":0},"conversion_rate":{"type":"number","format":"double"},"drop_off_rate":{"type":"number","format":"double"},"step_id":{"type":"integer","format":"int32"},"step_name":{"type":"string"},"step_order":{"type":"integer","format":"int32"}}},"StepResourceType":{"type":"string","description":"What kind of resource a migration step operates on","enum":["project","environment","deployment","environment-variable","service","domain","git-link","other"]},"StepResult":{"type":"object","description":"Result of executing a single migration step","required":["step_id","step_title","success","skipped","message","created_resources","duration_seconds"],"properties":{"created_resources":{"type":"array","items":{"$ref":"#/components/schemas/CreatedResource"},"description":"Resources created by this step"},"duration_seconds":{"type":"number","format":"double","description":"Duration of this step"},"message":{"type":"string","description":"Human-readable message about what happened"},"skipped":{"type":"boolean","description":"Whether this step was skipped"},"step_id":{"type":"string","description":"Step ID (matches `MigrationStep.id`)"},"step_title":{"type":"string","description":"Step title (for display)"},"success":{"type":"boolean","description":"Whether this step succeeded"}}},"StopSequence":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"StorageQuota":{"type":"object","description":"Quota usage information for a project.","required":["project_id","metrics_bytes","traces_bytes","logs_bytes","total_bytes","limit_bytes","usage_pct"],"properties":{"limit_bytes":{"type":"integer","format":"int64","minimum":0},"logs_bytes":{"type":"integer","format":"int64","minimum":0},"metrics_bytes":{"type":"integer","format":"int64","minimum":0},"project_id":{"type":"integer","format":"int32"},"total_bytes":{"type":"integer","format":"int64","minimum":0},"traces_bytes":{"type":"integer","format":"int64","minimum":0},"usage_pct":{"type":"number","format":"double"}}},"StripeConfig":{"type":"object","properties":{"include_unpriced_charges":{"type":"boolean","description":"When an allowlist is set, should we still ingest charges that\nlack a price reference (e.g. standalone `charge.succeeded` without\na subscription)? Default true — charges don't belong to a SKU."},"metered_mode":{"$ref":"#/components/schemas/MeteredMode","description":"How to compute MRR for metered / tiered / hybrid subscriptions."},"price_allowlist":{"type":"array","items":{"type":"string"},"description":"Only events tagged with one of these Stripe price IDs are ingested.\nEmpty = accept all prices."},"product_allowlist":{"type":"array","items":{"type":"string"},"description":"Only events tagged with one of these Stripe product IDs are\ningested. Empty = accept all products. Combined with\n`price_allowlist` via OR — if either list has a match, accept."}}},"SyncedRepositoryListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"language":{"type":["string","null"]},"owner":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"private":{"type":["boolean","null"]},"search":{"type":["string","null"]},"sort":{"type":["string","null"]}}},"SyntaxResult":{"type":"object","description":"Syntax validation result","required":["is_valid_syntax"],"properties":{"domain":{"type":["string","null"],"description":"The domain part of the email","example":"gmail.com"},"is_valid_syntax":{"type":"boolean","description":"Whether the email syntax is valid"},"suggestion":{"type":["string","null"],"description":"Suggested email correction if available"},"username":{"type":["string","null"],"description":"The username part of the email","example":"someone"}}},"TagInfo":{"type":"object","required":["name","commit_sha"],"properties":{"commit_sha":{"type":"string"},"name":{"type":"string"}}},"TagListResponse":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagInfo"}}}},"TailLogsRequest":{"type":"object","required":["project_id","service","env"],"properties":{"env":{"type":"string"},"external_service_id":{"type":["integer","null"],"format":"int32","description":"When set, tail an imported/managed external service's logs instead of\na project's (`project_id` is ignored in this mode)."},"levels":{"type":"array","items":{"type":"string"}},"project_id":{"type":"integer","format":"int32","description":"Project ID (integer, as used by the rest of the platform)"},"service":{"type":"string"},"text":{"type":["string","null"]}}},"TargetRecommendation":{"type":"object","description":"The temps/Hetzner target sizing and savings estimate","required":["server_type","vcpus","memory_gb","monthly_eur","fits_single_node","sizing_basis","rationale"],"properties":{"fits_single_node":{"type":"boolean","description":"Whether the workloads fit a single recommended server. When `false`,\nthe rationale explains the multi-node option (temps worker nodes)."},"memory_gb":{"type":"integer","format":"int32","description":"Memory (GB) of the recommended server"},"monthly_eur":{"type":"number","format":"double","description":"Estimated monthly price of the recommended server in EUR"},"monthly_savings_usd":{"type":["number","null"],"format":"double","description":"Estimated monthly savings in USD (current cost minus target cost,\ntreating EUR≈USD for the rough comparison — disclaimed in `notes`).\n`None` when the current cost is unknown."},"rationale":{"type":"string","description":"Human-readable recommendation summary"},"server_type":{"type":"string","description":"Recommended Hetzner server type (e.g. \"cpx32\")"},"sizing_basis":{"type":"string","description":"What the sizing was based on, e.g. \"2× measured usage + temps\nplatform overhead\" or \"resource requests (no metrics available)\""},"vcpus":{"type":"integer","format":"int32","description":"vCPUs of the recommended server"},"yearly_savings_usd":{"type":["number","null"],"format":"double","description":"`monthly_savings_usd × 12`"}}},"TemplateResponse":{"type":"object","description":"Response type for a single template","required":["slug","name","git","preset","tags","features","services","env_vars","is_featured"],"properties":{"description":{"type":["string","null"],"description":"Short description"},"env_vars":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarTemplateResponse"},"description":"Environment variables template"},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Container port the prebuilt image listens on (image deploys only)."},"features":{"type":"array","items":{"type":"string"},"description":"Feature highlights"},"git":{"$ref":"#/components/schemas/GitRefResponse","description":"Git repository reference"},"health_check_path":{"type":["string","null"],"description":"HTTP health-check path probed after the container starts (image deploys)."},"image":{"type":["string","null"],"description":"Prebuilt Docker image reference. When set, the one-click deploy pulls and\nruns this image directly (no build); when absent it builds from `git`."},"image_url":{"type":["string","null"],"description":"URL to template image/icon"},"is_featured":{"type":"boolean","description":"Whether the template is featured/promoted"},"name":{"type":"string","description":"Display name"},"preset":{"type":"string","description":"Framework/preset to use"},"screenshot_url":{"type":["string","null"],"description":"URL to a wide screenshot/banner preview of the deployed template.\nAbsent for templates that don't have one captured yet."},"services":{"type":"array","items":{"type":"string"},"description":"Required external services"},"slug":{"type":"string","description":"Unique identifier for the template (used in URLs)"},"tags":{"type":"array","items":{"type":"string"},"description":"Tags/categories for filtering"}}},"TestEmailRequest":{"type":"object","description":"Request body for testing an email provider","required":["from"],"properties":{"from":{"type":"string","description":"Sender email address (must be verified with the provider)","example":"test@example.com"},"from_name":{"type":["string","null"],"description":"Sender display name","example":"My App"}}},"TestEmailResponse":{"type":"object","description":"Response for test email endpoint","required":["success","sent_to"],"properties":{"error":{"type":["string","null"],"description":"Error message if the test failed"},"provider_message_id":{"type":["string","null"],"description":"Provider message ID if successful"},"sent_to":{"type":"string","description":"The email address the test was sent to","example":"user@example.com"},"success":{"type":"boolean","description":"Whether the test email was sent successfully"}}},"TestProviderKeyRequest":{"type":"object","required":["provider","api_key"],"properties":{"api_key":{"type":"string","description":"The raw API key to test"},"base_url":{"type":["string","null"],"description":"Optional custom base URL"},"provider":{"type":"string","description":"Provider ID: \"openai\", \"anthropic\", \"xai\", \"gemini\""}}},"TestProviderKeyResponse":{"type":"object","required":["success","provider","latency_ms"],"properties":{"error":{"type":["string","null"],"description":"Error message if the test failed"},"latency_ms":{"type":"integer","format":"int64","description":"Response time in milliseconds","minimum":0},"provider":{"type":"string"},"success":{"type":"boolean"}}},"TestProviderResponse":{"type":"object","required":["success"],"properties":{"message":{"type":["string","null"]},"success":{"type":"boolean"}}},"TimeBucketStats":{"type":"object","description":"Time bucket statistics response","required":["bucket","request_count","avg_response_time_ms","error_count","total_request_bytes","total_response_bytes"],"properties":{"avg_response_time_ms":{"type":"number","format":"double","description":"Average response time in milliseconds"},"bucket":{"type":"string","description":"Bucket timestamp in RFC3339 format","example":"2025-10-23T12:00:00Z"},"error_count":{"type":"integer","format":"int64","description":"Number of errors (status >= 400)"},"request_count":{"type":"integer","format":"int64","description":"Total number of requests in this bucket"},"total_request_bytes":{"type":"integer","format":"int64","description":"Total request bytes"},"total_response_bytes":{"type":"integer","format":"int64","description":"Total response bytes"}}},"TimeBucketStatsResponse":{"type":"object","description":"Response for time bucket stats","required":["stats","start_time","end_time","bucket_interval"],"properties":{"bucket_interval":{"type":"string"},"end_time":{"type":"string"},"start_time":{"type":"string"},"stats":{"type":"array","items":{"$ref":"#/components/schemas/TimeBucketStats"}}}},"TimeseriesBucket":{"type":"object","required":["bucket","request_count","input_tokens","output_tokens","avg_latency_ms"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"bucket":{"type":"string","description":"ISO 8601 timestamp"},"input_tokens":{"type":"integer","format":"int64"},"output_tokens":{"type":"integer","format":"int64"},"request_count":{"type":"integer","format":"int64"}}},"TimeseriesQueryParams":{"type":"object","properties":{"bucket":{"type":["string","null"],"description":"Bucket size: \"hour\", \"day\", \"week\" (defaults to \"day\")"},"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"model":{"type":["string","null"],"description":"Filter by model name"},"provider":{"type":["string","null"],"description":"Filter by provider name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"TlsMode":{"type":"string","enum":["None","Starttls","Tls"]},"TodayStatsResponse":{"type":"object","description":"Today's stats response","required":["total_requests","date"],"properties":{"date":{"type":"string","description":"Date for which stats are returned","example":"2025-10-23"},"total_requests":{"type":"integer","format":"int64","description":"Total requests today"}}},"ToggleDeploymentMetricsRequest":{"type":"object","description":"Request body to toggle OTLP metric ingestion for a deployment.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether to enable (`true`) or disable (`false`) metric ingestion."},"path":{"type":["string","null"],"description":"Prometheus scrape path (optional, defaults to `/metrics`)."},"port":{"type":["integer","null"],"format":"int32","description":"Prometheus scrape port (optional).","minimum":0}}},"ToggleServiceMetricsRequest":{"type":"object","description":"Request body to toggle metric collection for an external service.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether to enable (`true`) or disable (`false`) metric collection."}}},"TokenRenewalRequest":{"type":"object","required":["refresh_token"],"properties":{"refresh_token":{"type":"string"}}},"ToolCallEvent":{"type":"object","description":"Payload for the `tool_call` SSE event: the model is about to run a tool.\nSerialized as compact single-line JSON onto one `data:` line.","required":["id","name","arguments"],"properties":{"arguments":{"type":"string","description":"The raw JSON-args string the model emitted."},"id":{"type":"string"},"name":{"type":"string"}}},"ToolInfo":{"type":"object","description":"One persisted tool invocation + its result, attached to an assistant message.","required":["id","name","arguments"],"properties":{"arguments":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"result":{"type":["string","null"]}}},"ToolResultEvent":{"type":"object","description":"Payload for the `tool_result` SSE event: a tool finished running. Serialized\nas compact single-line JSON; `content` is JSON-string-escaped so it stays on\none `data:` line even when long.","required":["id","name","content"],"properties":{"content":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}}},"TopModelsQueryParams":{"type":"object","properties":{"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"limit":{"type":["integer","null"],"format":"int64","description":"Max results (defaults to 10)","minimum":0},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"TraceProjectRef":{"type":"object","description":"All projects that contributed spans to a trace, including their sharing flag.\n\nReturned by `CrossProjectTraceService::find_trace_projects`.","required":["project_id","project_name","project_slug","first_seen","sharing"],"properties":{"first_seen":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the project's single-project trace view."},"sharing":{"type":"boolean","description":"Whether this project has `cross_project_trace_sharing = true`."}}},"TraceSummariesResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TraceSummary"}},"total":{"type":["integer","null"],"format":"int64","description":"Total traces matching the filters, ignoring pagination. Omitted when\nthe request passed `include_total=false`, in which case the caller\nasked not to pay for the count — treat its absence as \"unknown\", not\nas zero.","minimum":0}}},"TraceSummary":{"type":"object","description":"A trace summary for the list view — one row per trace, aggregated from spans.","required":["trace_id","root_span_name","service_name","kind","status_code","start_time","duration_ms","span_count","error_count"],"properties":{"deployment_environment":{"type":["string","null"],"description":"The deployment environment from the root span's resource attributes (e.g. \"production\")."},"duration_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"kind":{"$ref":"#/components/schemas/SpanKind"},"root_span_name":{"type":"string"},"service_name":{"type":"string"},"span_count":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"trace_id":{"type":"string"}}},"TracesResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/SpanRecord"}}}},"TrackedLinkResponse":{"type":"object","description":"Tracked link with click count","required":["link_index","original_url","click_count"],"properties":{"click_count":{"type":"integer","format":"int32"},"link_index":{"type":"integer","format":"int32"},"original_url":{"type":"string"}}},"TrackingEventResponse":{"type":"object","description":"Email tracking event","required":["id","email_id","event_type","created_at"],"properties":{"created_at":{"type":"string"},"email_id":{"type":"string"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"ip_address":{"type":["string","null"]},"link_index":{"type":["integer","null"],"format":"int32"},"link_url":{"type":["string","null"]},"user_agent":{"type":["string","null"]}}},"TriggerAgentRequest":{"type":"object","properties":{"trigger_source_id":{"type":["integer","null"],"format":"int32"},"trigger_source_type":{"type":["string","null"]},"user_context":{"type":["string","null"],"description":"Optional context from the user (e.g. a research topic, bug description, or instructions)."}}},"TriggerDigestResponse":{"type":"object","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"TriggerPipelinePayload":{"type":"object","properties":{"branch":{"type":["string","null"]},"commit":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID - if not provided, will use the project's preview environment"},"tag":{"type":["string","null"]}}},"TriggerPipelineResponse":{"type":"object","required":["message","project_id","environment_id"],"properties":{"branch":{"type":["string","null"]},"commit":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"message":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"tag":{"type":["string","null"]}}},"TriggerScanRequest":{"type":"object","required":["environment_id"],"properties":{"environment_id":{"type":"integer","format":"int32","description":"Environment ID to scan (uses the current deployment for this environment)","example":1}}},"TriggerScanResponse":{"type":"object","required":["scan_id","status","message"],"properties":{"message":{"type":"string"},"scan_id":{"type":"integer","format":"int32"},"status":{"type":"string"}}},"TtlRequest":{"type":"object","description":"Request to get TTL for a key","required":["key"],"properties":{"key":{"type":"string","description":"The key to check TTL for","example":"session:abc"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"TtlResponse":{"type":"object","description":"Response for TTL operation","required":["ttl"],"properties":{"ttl":{"type":"integer","format":"int64","description":"TTL in seconds, -1 if no expiration, -2 if key doesn't exist","example":3600}}},"TxtRecord":{"type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string"}}},"UiManifest":{"type":"object","description":"Describes the plugin's embedded UI bundle.","required":["entry_js"],"properties":{"css":{"type":"array","items":{"type":"string"},"description":"CSS files to load"},"entry_js":{"type":"string","description":"JavaScript entry point filename relative to the bundle root"},"routes":{"type":"array","items":{"$ref":"#/components/schemas/UiRoute"},"description":"Client-side routes the plugin handles"}}},"UiRoute":{"type":"object","description":"A client-side route provided by the plugin UI.","required":["path","title"],"properties":{"path":{"type":"string","description":"Route path pattern (e.g., \"/my-plugin\", \"/my-plugin/:id\")"},"title":{"type":"string","description":"Page title for breadcrumbs"}}},"UndrainNodeResponse":{"type":"object","description":"Response after undraining (reactivating) a node.","required":["id","name","status","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"UnifiedTrace":{"type":"object","description":"Merged cross-project trace result (Phase 2 unified waterfall).\n\nSpans are sorted by `start_time ASC`. At most 20 projects and 10,000\nspans total are included; `truncated` / `truncated_projects` signal when\nthe caps were hit.","required":["trace_id","projects","spans","start_time","end_time","total_duration_ms","span_count","error_count","has_redacted_spans","truncated","truncated_projects"],"properties":{"end_time":{"type":"string","format":"date-time"},"error_count":{"type":"integer","minimum":0},"has_redacted_spans":{"type":"boolean","description":"`true` when at least one project has `cross_project_trace_sharing = false`\nand its spans were therefore excluded from the result set."},"projects":{"type":"array","items":{"$ref":"#/components/schemas/ProjectRef"},"description":"Projects that contributed spans to this result set."},"span_count":{"type":"integer","minimum":0},"spans":{"type":"array","items":{"$ref":"#/components/schemas/AnnotatedSpan"},"description":"Annotated, merged span list sorted by `start_time ASC`."},"start_time":{"type":"string","format":"date-time"},"total_duration_ms":{"type":"number","format":"double","description":"Trace wall-clock duration in milliseconds (`end_time – start_time`)."},"trace_id":{"type":"string"},"truncated":{"type":"boolean","description":"`true` when the 20-project or 10,000-span cap was hit."},"truncated_projects":{"type":"array","items":{"type":"integer","format":"int32"},"description":"project_ids excluded due to truncation (most-recent first_seen dropped first)."}}},"UniqueCountsQuery":{"type":"object","description":"Query parameters for unique counts over time frame","required":["start_date","end_date"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"metric":{"type":"string","description":"Metric to count: \"sessions\" (unique sessions), \"visitors\" (unique visitors),\n\"returning_visitors\" (visitors seen before the range), or \"page_views\"\n(total page views) (default: \"sessions\")"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"UniqueCountsResponse":{"type":"object","required":["count"],"properties":{"count":{"type":"integer","format":"int64"}}},"UnsupportedFeature":{"type":"object","description":"A feature from the source platform that cannot be migrated","required":["feature","reason"],"properties":{"alternative":{"type":["string","null"],"description":"Suggested alternative in Temps (if any)"},"feature":{"type":"string","description":"Feature name (e.g., \"Edge Middleware\", \"Serverless Functions\", \"Cron Jobs\")"},"reason":{"type":"string","description":"Why it can't be migrated"}}},"UpdateAdminGateRequest":{"type":"object","required":["allowed_ips","allowed_hosts","trust_forwarded_for"],"properties":{"allowed_hosts":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"}},"trust_forwarded_for":{"type":"boolean"}}},"UpdateAiProviderRequest":{"type":"object","description":"Body for `PATCH /settings/ai-providers/{provider_id}` — updates\nprovider-scoped settings (just the default model for now) without\ntouching the credential. Keeping credentials out of this shape means\nthe UI can auto-save model changes on select, without forcing the user\nto re-paste their token or config file.\nName-spaced schema name avoids an OpenAPI collision with\n`temps-notifications::UpdateProviderRequest`, which has different fields.\nBoth are exposed as `utoipa::ToSchema`; without the override the merged\nOpenAPI doc would silently shadow one struct with the other and break\ngenerated CLI/web clients.","properties":{"default_model":{"type":["string","null"],"description":"New default model id. `None` or an empty string clears the stored\nvalue so the CLI falls back to its own default."},"max_turns_analysis":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer analysis phase (1–200). `0`\nclears the stored value (built-in default applies); omitted/`None`\nleaves the current value unchanged — so a PATCH that only updates\n`default_model` doesn't wipe the turn settings."},"max_turns_feedback":{"type":["integer","null"],"format":"int32","description":"Default max turns for autofixer feedback rounds (1–200). `0` clears;\nomitted leaves unchanged."},"max_turns_fix":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer fix phase (1–200). `0` clears;\nomitted leaves unchanged."}}},"UpdateAiProviderResponse":{"type":"object","required":["provider_id"],"properties":{"default_model":{"type":["string","null"]},"max_turns_analysis":{"type":["integer","null"],"format":"int32"},"max_turns_feedback":{"type":["integer","null"],"format":"int32"},"max_turns_fix":{"type":["integer","null"],"format":"int32"},"provider_id":{"type":"string"}}},"UpdateAlertRuleRequest":{"type":"object","properties":{"cooldown_minutes":{"type":["integer","null"],"format":"int32"},"enabled":{"type":["boolean","null"]},"environment_filter":{"type":["integer","null"],"format":"int32"},"error_level_filter":{"type":["string","null"]},"name":{"type":["string","null"]},"notification_priority":{"type":["string","null"]},"trigger_config":{},"trigger_type":{"type":["string","null"]}}},"UpdateApiKeyRequest":{"type":"object","properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"]},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["projects:read","deployments:read"]}}},"UpdateAutomaticDeployRequest":{"type":"object","required":["automatic_deploy"],"properties":{"automatic_deploy":{"type":"boolean"}}},"UpdateBackupScheduleRequest":{"type":"object","description":"Request body for updating an existing backup schedule via `PATCH /api/backups/schedules/{id}`.\n\nAll fields are optional; only present fields are updated. Absent fields\nleave the corresponding column unchanged.","properties":{"description":{"type":["string","null"],"description":"New human-readable description. Pass an empty string `\"\"` to clear."},"enabled":{"type":["boolean","null"],"description":"Enable or disable the schedule. Skipped when `None`."},"include_control_plane":{"type":["boolean","null"],"description":"Toggle whether the control-plane backup is produced on every run."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Per-schedule wall-clock timeout override (seconds).\n\n- `None` (field absent) — leave current value unchanged\n- `Some(None)` (field present, JSON `null`) — clear override; fall back to engine default\n- `Some(Some(n))` — set to `n` seconds (must be >= 60)"},"name":{"type":["string","null"],"description":"New schedule name. Skipped when `None`. Must not be empty if provided."},"retention_period":{"type":["integer","null"],"format":"int32","description":"Days to retain backups produced by this schedule. Must be >= 1."},"schedule_expression":{"type":["string","null"],"description":"New cron expression. When changed, `next_run` is recomputed."},"tags":{"type":["array","null"],"items":{"type":"string"},"description":"Replace the full tag list. Skipped when `None`."},"target_all_services":{"type":["boolean","null"],"description":"Toggle between \"back up every database\" (`true`) and \"back up only\nthe explicit list\" (`false`). When set to `true`, the server clears\nthe explicit membership rows for this schedule."}}},"UpdateBlobRequest":{"type":"object","description":"Request to update Blob service configuration","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (e.g., \"rustfs/rustfs:1.0.0-alpha.98\")","example":"rustfs/rustfs:1.0.0-alpha.98"}}},"UpdateBlobResponse":{"type":"object","description":"Response after updating Blob service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service updated successfully"},"status":{"$ref":"#/components/schemas/BlobStatusResponse","description":"Current status"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"UpdateCloudflareProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/CloudflareConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateConfigBody":{"type":"object","properties":{"config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProviderConfig","description":"Typed provider configuration. Setting `config` to `null` clears\nthe stored config back to the accept-everything default. The\nconfig's `provider` tag must match the integration's provider."}]}}},"UpdateCustomDomainRequest":{"type":"object","properties":{"branch":{"type":["string","null"]},"domain":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to (empty string clears it)"},"status_code":{"type":["integer","null"],"format":"int32"}}},"UpdateDashboardRequest":{"type":"object","properties":{"layout":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DashboardLayout"}]},"name":{"type":["string","null"]}}},"UpdateDeploymentConfigRequest":{"type":"object","properties":{"automaticDeploy":{"type":["boolean","null"]},"cpuLimit":{"type":["integer","null"],"format":"int32"},"cpuRequest":{"type":["integer","null"],"format":"int32"},"crossArchitectureBuilds":{"type":["boolean","null"],"description":"Build one image per architecture the eligible nodes run. Off by\ndefault; environments inherit this and may override it. Cross-builds\nare emulated on the control plane and substantially slower, so they are\nopted into rather than triggered by cluster topology."},"exposedPort":{"type":["integer","null"],"format":"int32"},"memoryLimit":{"type":["integer","null"],"format":"int32"},"memoryRequest":{"type":["integer","null"],"format":"int32"},"performanceMetricsEnabled":{"type":["boolean","null"]},"replicas":{"type":["integer","null"],"format":"int32"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig"}]},"sessionRecordingEnabled":{"type":["boolean","null"]}}},"UpdateDeploymentTokenRequest":{"type":"object","properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"]},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["visitors:enrich","emails:send"]}}},"UpdateDnsProviderRequest":{"type":"object","description":"Request to update a DNS provider","properties":{"credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DnsProviderCredentials","description":"New credentials"}]},"description":{"type":["string","null"],"description":"New description"},"is_active":{"type":["boolean","null"],"description":"Active status"},"name":{"type":["string","null"],"description":"New name"}}},"UpdateEmailProviderRequest":{"type":"object","description":"Request body for `PATCH /email-providers/{id}`.\n\nAll fields are optional. Omit any field to leave it unchanged. The\n`provider_type` is immutable — to switch providers, delete the row and\ncreate a new one. For credentials, supplying any credential variant\nre-encrypts the stored blob; omitting them preserves the existing secret\n(so operators can rename without re-typing passwords).","properties":{"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"],"example":"My AWS SES"},"region":{"type":["string","null"],"example":"us-east-1"},"scaleway_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ScalewayCredentialsRequest"}]},"ses_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SesCredentialsRequest"}]},"smtp_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SmtpCredentialsRequest"}]},"sns_topic_arn":{"type":["string","null"],"description":"Rotate or clear the exact SNS topic allowed for this SES provider.\nOmit to preserve it, send `null` to clear it, or send a string to set it."}}},"UpdateEnvironmentSettingsRequest":{"type":"object","properties":{"anti_affinity":{"type":["boolean","null"],"description":"Anti-affinity: spread replicas across different nodes.\nWhen enabled, the scheduler avoids placing two replicas of the same\nenvironment on the same node. Defaults to `true`."},"attack_mode":{"type":["boolean","null"],"description":"Per-environment CAPTCHA attack-mode override (tri-state):\n- absent → leave the current override unchanged\n- JSON `null` → clear the override (inherit the project-level setting)\n- `true`/`false` → override the project setting for this environment"},"automatic_deploy":{"type":["boolean","null"],"description":"Enable/disable automatic deployments for this environment"},"branch":{"type":["string","null"]},"cpu_limit":{"type":["integer","null"],"format":"int32","description":"Maximum (limit) CPU in microcores. Send JSON `null` to clear → \"no limit\".\nAbsent leaves the current value unchanged."},"cpu_request":{"type":["integer","null"],"format":"int32","description":"Minimum (request) CPU in microcores. Send JSON `null` to clear (no request).\nAbsent leaves the current value unchanged."},"cross_architecture_builds":{"type":["boolean","null"],"description":"Build one image per architecture the eligible nodes run (overrides the\nproject-level setting). Off by default: cross-architecture builds are\nemulated on the control plane and substantially slower, so they are\nopted into per environment rather than triggered by cluster topology."},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container (overrides project-level port for this environment)\n\nPriority order for port resolution:\n1. Image EXPOSE directive (auto-detected from built image)\n2. This environment-level exposed_port (overrides project setting)\n3. Project-level exposed_port (fallback)\n4. Default: 3000","example":8080},"force_https":{"type":["boolean","null"],"description":"Per-environment HTTP→HTTPS redirect override (tri-state):\n- absent → leave the current override unchanged\n- JSON `null` → clear the override (inherit the proxy default, which\n redirects only when the host has an active TLS certificate)\n- `true` → always redirect plain HTTP to HTTPS for this environment,\n even when no local certificate exists (TLS terminated upstream)\n- `false` → never redirect this environment, even when a certificate does\n exist\n\nRequests under `/.well-known/acme-challenge/` are never redirected\nregardless of this setting, so ACME HTTP-01 validation always completes."},"idle_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Seconds of inactivity before stopping containers (60-86400). Default: 300."},"memory_limit":{"type":["integer","null"],"format":"int32","description":"Maximum (limit) memory in MB. Send JSON `null` to clear → \"no limit\".\nAbsent leaves the current value unchanged."},"memory_request":{"type":["integer","null"],"format":"int32","description":"Minimum (request) memory in MB. Send JSON `null` to clear (no request).\nAbsent leaves the current value unchanged."},"on_demand":{"type":["boolean","null"],"description":"Enable on-demand mode (scale-to-zero). Containers are stopped after\nidle_timeout_seconds of no traffic and started on the next request."},"password":{"type":["string","null"],"description":"Set a password to protect this environment. The proxy will show an HTML\npassword form before allowing access. The password is bcrypt-hashed\nserver-side and never stored in plaintext.\nSend an empty string to remove password protection."},"performance_metrics_enabled":{"type":["boolean","null"],"description":"Enable/disable performance metrics collection"},"protected":{"type":["boolean","null"],"description":"When true, git pushes do NOT auto-deploy to this environment.\nDeployments must be promoted from another environment."},"replicas":{"type":["integer","null"],"format":"int32"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig","description":"Security configuration for this environment (overrides project-level settings)"}]},"session_recording_enabled":{"type":["boolean","null"],"description":"Enable/disable session recording"},"target_labels":{"description":"Label selector for node-based scheduling (overrides project-level setting).\nSame key with array value -> OR, different keys -> AND.\nExample: `{\"region\": [\"us\", \"asia\"], \"gpu\": \"true\"}`"},"target_nodes":{"type":["array","null"],"items":{"type":"integer","format":"int32"},"description":"Optional list of node IDs to deploy to (overrides project-level setting)"},"wake_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Max seconds to wait for containers to start on wake (5-120). Default: 30."}}},"UpdateEnvironmentSubdomainRequest":{"type":"object","description":"Request to rename an environment's auto-managed subdomain.\n\nThe subdomain is the host label inserted in front of the platform's\npreview domain (e.g. `myapp` in `myapp.preview.temps.sh`). Renaming\nreplaces the previous subdomain entirely — the old hostname stops\nresolving immediately after this request succeeds.","required":["subdomain"],"properties":{"subdomain":{"type":"string","description":"New subdomain label. Must be a DNS-safe slug (lowercase letters,\ndigits, and hyphens, 1-63 characters). The value is slugified\nserver-side, so casing and disallowed characters are normalized.","example":"myapp"}}},"UpdateEnvironmentVariableRequest":{"type":"object","required":["key","environment_ids"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean"},"is_secret":{"type":["boolean","null"],"description":"Optional secret-flag transition.\n- `Some(true)` promotes a regular var to a secret.\n- `Some(false)` is rejected if the row is already secret (one-way flag).\n- `None` (omitted) leaves the flag unchanged."},"key":{"type":"string"},"value":{"type":["string","null"],"description":"New plaintext value. `None` (omitted) keeps the existing ciphertext,\nwhich is the only way to edit a secret env var without re-typing its\nvalue (e.g. changing which environments it applies to)."}}},"UpdateErrorGroupRequest":{"type":"object","required":["status"],"properties":{"assigned_to":{"type":["string","null"]},"status":{"type":"string"}}},"UpdateExternalServiceRequest":{"type":"object","required":["parameters"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use for the service (e.g., \"gotempsh/postgres-walg:18-bookworm\", \"timescale/timescaledb-ha:pg18\")\nWhen provided, the service will be recreated with the new image while preserving data"},"parameters":{"type":"object","additionalProperties":{},"propertyNames":{"type":"string"}}}},"UpdateFlagRequest":{"type":"object","properties":{"client_visible":{"type":["boolean","null"]},"default_value":{"description":"Must match the flag's existing `value_type`."},"description":{"type":["string","null"],"description":"Tri-state: absent leaves it, `null` clears it, a string sets it."}}},"UpdateGitSettingsRequest":{"type":"object","required":["main_branch","repo_owner","repo_name","directory"],"properties":{"directory":{"type":"string"},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"],"description":"Git clone URL for public repositories"},"is_public_repo":{"type":["boolean","null"],"description":"Whether this is a public repository (no git provider connection needed)"},"main_branch":{"type":"string"},"preset":{"type":["string","null"]},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration (e.g., Dockerfile path for Docker preset)\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"repo_name":{"type":"string"},"repo_owner":{"type":"string"}}},"UpdateIncidentStatusRequest":{"type":"object","required":["status","message"],"properties":{"message":{"type":"string"},"status":{"type":"string"}}},"UpdateIpAccessControlRequest":{"type":"object","description":"Request to update an IP access control rule","properties":{"action":{"type":["string","null"],"description":"Optional new action"},"ip_address":{"type":["string","null"],"description":"Optional new IP address"},"reason":{"type":["string","null"],"description":"Optional new reason"}}},"UpdateKvRequest":{"type":"object","description":"Request to update KV service configuration","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (e.g., \"gotempsh/redis-walg:8-bookworm\")","example":"gotempsh/redis-walg:8-bookworm"}}},"UpdateKvResponse":{"type":"object","description":"Response after updating KV service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service updated successfully"},"status":{"$ref":"#/components/schemas/KvStatusResponse","description":"Current service status"},"success":{"type":"boolean","description":"Whether the operation succeeded"}}},"UpdateManagedDomainApiRequest":{"type":"object","description":"Request to update a managed domain's settings.","properties":{"auto_manage":{"type":["boolean","null"],"description":"Toggle automatic DNS management for this domain."},"generated_hostname_mode":{"type":["string","null"],"description":"`\"standard\"` or `\"flat\"`. Persisted as-is; switching to `\"flat\"` does not\nrecompute existing hostnames — use the apply endpoint for that."},"sync_generated_records":{"type":["boolean","null"],"description":"Toggle DNS record sync for this domain."}}},"UpdateMcpRequest":{"type":"object","required":["config"],"properties":{"config":{"type":"object"},"description":{"type":["string","null"]},"name":{"type":["string","null"]}}},"UpdateMetricAlertRequest":{"type":"object","properties":{"aggregation":{"type":["string","null"]},"detection_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DetectionConfig","description":"Replaces the detector wholesale when present (absent = leave unchanged)."}]},"dynamic_alerts":{"type":["boolean","null"],"description":"Toggles per-series (\"dynamic\") alerting (absent = leave unchanged)."},"enabled":{"type":["boolean","null"]},"for_duration_secs":{"type":["integer","null"],"format":"int32"},"group_by":{"type":["array","null"],"items":{"type":"string"},"description":"Replaces the group_by keys wholesale when present (absent = leave unchanged)."},"grouped_notification_threshold":{"type":["integer","null"],"format":"int32","description":"Updates the notification-grouping threshold (absent = leave unchanged)."},"label_filters":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"Replaces the label filters wholesale when present (absent = leave unchanged)."},"max_series":{"type":["integer","null"],"format":"int32","description":"Updates the dynamic-alerting cardinality cap (absent = leave unchanged)."},"metric_name":{"type":["string","null"]},"name":{"type":["string","null"]},"severity":{"type":["string","null"]},"window_secs":{"type":["integer","null"],"format":"int32"}}},"UpdateNotificationEmailProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/EmailConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateOidcProviderRequest":{"type":"object","properties":{"client_id":{"type":["string","null"]},"client_secret":{"type":["string","null"]},"default_role":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"group_claim":{"type":["string","null"]},"issuer_url":{"type":["string","null"]},"jit_provisioning":{"type":["boolean","null"]},"name":{"type":["string","null"]},"role_claim":{"type":["string","null"]},"scopes":{"type":["string","null"]},"template":{"type":["string","null"]},"trust_idp_email":{"type":["boolean","null"]}}},"UpdatePreferencesRequest":{"type":"object","required":["preferences"],"properties":{"preferences":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}},"UpdateProjectSecretRequest":{"type":"object","description":"Request to update a project secret. The `value` field is optional — omit it\nto rotate only the environment scoping / preview flag without touching the\nciphertext.","properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean"},"value":{"type":["string","null"],"description":"New plaintext value, <= 1 MiB. Omit to keep the existing value."}}},"UpdateProjectSettingsRequest":{"type":"object","properties":{"ai_alert_summaries_enabled":{"type":["boolean","null"],"description":"Opt in to AI summarization of metric alert notifications (ADR-021)."},"ai_debug_chat_enabled":{"type":["boolean","null"],"description":"Opt in to AI debugging chat, e.g. on deployment failures (ADR-023)."},"ai_write_actions_enabled":{"type":["boolean","null"],"description":"Opt in to AI propose-then-confirm write capability."},"attack_mode":{"type":["boolean","null"],"description":"Enable/disable attack mode (CAPTCHA protection) for all project environments"},"cross_project_trace_sharing":{"type":["boolean","null"],"description":"ADR-027 Phase 3 opt-out: set to false to suppress this project's traces\nfrom appearing in cross-project discovery results. Default true (consistent\nwith the OSS global-observability model). Omit to leave unchanged."},"directory":{"type":["string","null"]},"enable_preview_environments":{"type":["boolean","null"],"description":"Enable automatic preview environment creation for each branch"},"error_source_context_enabled":{"type":["boolean","null"],"description":"Opt in to native error-tracking source context (source-file upload +\nsource code shown in stack traces)."},"error_source_root":{"type":["string","null"],"description":"Set the auto-capture source root (relative to the checkout). Send an\nempty string to clear it back to the build-context default. Omit to\nleave unchanged."},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"main_branch":{"type":["string","null"]},"preset":{"type":["string","null"]},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration (e.g., Dockerfile path for Docker preset)\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"preview_envs_idle_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Idle timeout (seconds, 60..=86400) for on-demand preview environments."},"preview_envs_on_demand":{"type":["boolean","null"],"description":"When true, newly-created preview environments default to on-demand mode."},"preview_envs_wake_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Wake timeout (seconds, 5..=120) for on-demand preview environments."},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"slug":{"type":["string","null"]}}},"UpdateProviderCredentialsRequest":{"type":"object","description":"Partial-update payload for provider credentials. Every field is optional;\nonly the fields the user re-enters are applied. The server validates that\nthe fields supplied make sense for the provider's current auth_method\n(e.g. `app_id` + `private_key` only apply to GitHub Apps).","properties":{"app_id":{"type":["string","null"],"description":"Application ID (GitHub App integer as string; GitLab App string)."},"app_secret":{"type":["string","null"],"description":"GitLab App secret (not used by GitHub App — use `client_secret`)."},"client_id":{"type":["string","null"],"description":"OAuth client ID (GitLab OAuth, GitHub App)."},"client_secret":{"type":["string","null"],"description":"OAuth client secret (GitLab OAuth, GitHub App)."},"private_key":{"type":["string","null"],"description":"GitHub App private key (PEM)."},"redirect_uri":{"type":["string","null"],"description":"OAuth redirect URI (GitLab OAuth / GitLab App)."},"token":{"type":["string","null"],"description":"PAT for PAT-type providers."},"webhook_secret":{"type":["string","null"],"description":"GitHub App webhook secret."}}},"UpdateProviderKeyRequest":{"type":"object","properties":{"api_key":{"type":["string","null"]},"base_url":{"type":["string","null"],"description":"Double-Option: absent = leave unchanged, present-null = clear (revert to\nthe provider's default endpoint), present-value = set."},"default_model":{"type":["string","null"],"description":"Double-Option: absent = leave unchanged, present-null = clear the pinned\nmodel (revert to the per-provider default), present-value = set."},"display_name":{"type":["string","null"]},"is_active":{"type":["boolean","null"]}}},"UpdateProviderRequest":{"type":"object","properties":{"config":{},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateRouteRequest":{"type":"object","required":["host","port","enabled"],"properties":{"enabled":{"type":"boolean"},"host":{"type":"string"},"port":{"type":"integer","format":"int32"},"route_type":{"type":["string","null"],"description":"Route type: \"http\" (default) matches on HTTP Host header,\n\"tls\" matches on TLS SNI hostname for TCP passthrough"}}},"UpdateS3SourceRequest":{"type":"object","properties":{"access_key_id":{"type":["string","null"],"description":"Optional new access key ID","example":"AKIAXXXXXXXXXXXXXXXX"},"bucket_name":{"type":["string","null"],"description":"Optional new bucket name"},"bucket_path":{"type":["string","null"],"description":"Optional new bucket path"},"endpoint":{"type":["string","null"],"description":"Optional new endpoint URL for S3-compatible services","example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"],"description":"Optional new path-style addressing setting","example":true},"name":{"type":["string","null"],"description":"Optional new name for the source"},"region":{"type":["string","null"],"description":"Optional new region"},"secret_key":{"type":["string","null"],"description":"Optional new secret key"}}},"UpdateSecretBody":{"type":"object","required":["signing_secret"],"properties":{"signing_secret":{"type":"string","description":"New signing secret from the provider's dashboard. Encrypted at\nrest; never returned in any API response."}}},"UpdateSelfRequest":{"type":"object","properties":{"email":{"type":["string","null"],"example":"john.doe@example.com"},"name":{"type":["string","null"],"example":"John Doe"}}},"UpdateSessionDurationRequest":{"type":"object","required":["duration"],"properties":{"duration":{"type":"integer","format":"int32"}}},"UpdateSessionDurationResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"UpdateSkillRequest":{"type":"object","properties":{"content":{"type":["string","null"]},"description":{"type":["string","null"]},"name":{"type":["string","null"]}}},"UpdateSlackProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/SlackConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateSpeedMetricsPayload":{"type":"object","description":"Update speed metrics payload for late-loading metrics","properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"}}},"UpdateStatusResponse":{"type":"object","description":"Result of the background release-update check, driving the web console's\nupgrade banner. All optional fields are set together iff\n`update_available` is true.","required":["update_available","docs_url"],"properties":{"channel":{"type":["string","null"],"description":"Channel the install tracks: `stable` or `beta`."},"checked_at":{"type":["string","null"],"description":"When the check that found the update ran (ISO 8601, UTC)."},"current_version":{"type":["string","null"],"description":"Version tag of the running binary, e.g. `v0.1.0-beta.45`."},"docs_url":{"type":"string","description":"Docs page with upgrade instructions. Always present so the UI links\nthe same page regardless of update state."},"latest_version":{"type":["string","null"],"description":"Newest published tag on this install's channel."},"release_url":{"type":["string","null"],"description":"Release-notes page (GitHub release) for the newer version."},"update_available":{"type":"boolean","description":"True when a newer release than the running binary has been published\non this install's channel."}}},"UpdateTokenRequest":{"type":"object","required":["access_token"],"properties":{"access_token":{"type":"string"},"refresh_token":{"type":["string","null"]}}},"UpdateTokenResponse":{"type":"object","required":["connection_id","message","is_active"],"properties":{"connection_id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"message":{"type":"string"}}},"UpdateUserRequest":{"type":"object","properties":{"email":{"type":["string","null"],"example":"john.doe@example.com"},"name":{"type":["string","null"],"example":"John Doe"}}},"UpdateWebhookProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/WebhookConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateWebhookRequestBody":{"type":"object","properties":{"enabled":{"type":["boolean","null"],"description":"Whether the webhook is enabled"},"events":{"type":["array","null"],"items":{"type":"string"},"description":"Event types to subscribe to"},"secret":{"type":["string","null"],"description":"Secret for HMAC signature verification"},"url":{"type":["string","null"],"description":"Target URL for webhook delivery"}}},"UpgradeExternalServiceRequest":{"type":"object","required":["docker_image"],"properties":{"docker_image":{"type":"string","description":"Docker image to upgrade to (e.g., \"gotempsh/postgres-walg:18-bookworm\")\nThis will trigger pg_upgrade for PostgreSQL or equivalent upgrade procedures for other services","example":"gotempsh/postgres-walg:18-bookworm"}}},"UpgradeRequest":{"type":"object","required":["image"],"properties":{"image":{"type":"string","description":"Image reference to pull and run (e.g.\n`ghcr.io/gotempsh/temps-preview-gateway:latest`). Empty resets to default."}}},"UpsertAgentRequest":{"type":"object","properties":{"ai_model":{"type":["string","null"],"description":"Preferred model identifier for the CLI. `Some(\"\")` clears the stored value."},"ai_provider":{"type":["string","null"]},"ai_provider_key_id":{"type":["integer","null"],"format":"int32"},"api_key":{"type":["string","null"],"description":"Plain-text API key — will be encrypted before storage"},"branch_prefix":{"type":["string","null"]},"config_repo_branch":{"type":["string","null"],"description":"Branch of the config repo to use (default: \"main\")."},"config_repo_url":{"type":["string","null"],"description":"Private config repo containing .claude/ directory (skills, MCP, plugins)."},"cooldown_minutes":{"type":["integer","null"],"format":"int32"},"daily_budget_cents":{"type":["integer","null"],"format":"int32"},"deliverable":{"type":["string","null"]},"description":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"max_turns":{"type":["integer","null"],"format":"int32"},"mcp_servers_config":{"description":"MCP servers config (Claude Code settings.json mcpServers format).\nCredential-bearing legacy inline objects are write-only: normal reads\nmask them, and updates must omit this field to preserve existing values."},"name":{"type":["string","null"]},"prompt":{"type":["string","null"]},"sandbox_enabled":{"type":["boolean","null"]},"skills_config":{"description":"Skills config as JSON array."},"slug":{"type":["string","null"]},"timeout_seconds":{"type":["integer","null"],"format":"int32"},"tools_config":{"description":"Tools config as JSON array. Custom-tool webhook URLs and headers are\nwrite-only; omit this field on update to preserve them."},"trigger_config":{"description":"Trigger configuration JSON: { \"error\": { \"new_issue\": true, \"regression\": true }, \"manual\": true }"}}},"UpsertSecretRequest":{"type":"object","required":["name","value"],"properties":{"description":{"type":["string","null"]},"mount_path":{"type":["string","null"],"description":"Required for \"file\" type secrets — absolute path inside the sandbox"},"name":{"type":"string"},"secret_type":{"type":"string","description":"\"env\" (environment variable) or \"file\" (written to mount_path)"},"value":{"type":"string"}}},"UptimeDataPoint":{"type":"object","required":["timestamp","status"],"properties":{"error_message":{"type":["string","null"]},"response_time_ms":{"type":["integer","null"],"format":"int32"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"UptimeHistoryResponse":{"type":"object","required":["monitor_id","uptime_data"],"properties":{"monitor_id":{"type":"integer","format":"int32"},"uptime_data":{"type":"array","items":{"$ref":"#/components/schemas/UptimeDataPoint"}}}},"UsageFilter":{"type":"object","description":"Filters for querying AI usage data.\n\nCost bounds are expressed in microcents (the unit stored in\n`estimated_cost_microcents`). At most one of `gte`/`gt` and one of\n`lte`/`lt` is meaningful per query; if both are set the stricter wins\nnaturally because they are ANDead together.","properties":{"conversation_id":{"type":["string","null"]},"cost_gt":{"type":["integer","null"],"format":"int64","description":"Cost strictly greater-than, in microcents."},"cost_gte":{"type":["integer","null"],"format":"int64","description":"Cost greater-than-or-equal, in microcents."},"cost_lt":{"type":["integer","null"],"format":"int64","description":"Cost strictly less-than, in microcents."},"cost_lte":{"type":["integer","null"],"format":"int64","description":"Cost less-than-or-equal, in microcents."},"model":{"type":["string","null"]},"provider":{"type":["string","null"]},"status":{"type":["integer","null"],"format":"int32","description":"Filter by HTTP status code (exact match)."},"tags":{"type":["string","null"],"description":"Comma-separated tags to filter by (AND logic)."},"tokens_gt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly greater-than."},"tokens_gte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) greater-than-or-equal."},"tokens_lt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly less-than."},"tokens_lte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) less-than-or-equal."},"user_id":{"type":["integer","null"],"format":"int32"}}},"UsageInfo":{"type":"object","required":["prompt_tokens","completion_tokens","total_tokens"],"properties":{"completion_tokens":{"type":"integer","format":"int64"},"prompt_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"UsageLogEntry":{"type":"object","required":["id","timestamp","provider","model","input_tokens","output_tokens","latency_ms","estimated_cost_microcents","status","is_streaming","is_byok","tags"],"properties":{"conversation_id":{"type":["string","null"]},"estimated_cost_microcents":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int64"},"input_tokens":{"type":"integer","format":"int64"},"is_byok":{"type":"boolean"},"is_streaming":{"type":"boolean"},"latency_ms":{"type":"integer","format":"int32"},"model":{"type":"string"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_id":{"type":["string","null"]},"status":{"type":"integer","format":"int32"},"tags":{"type":"array","items":{"type":"string"}},"timestamp":{"type":"string"},"trace_id":{"type":["string","null"]}}},"UsageLogPage":{"type":"object","description":"A page of recent usage log entries plus the total count for pagination.","required":["entries","total"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/UsageLogEntry"},"description":"The usage log entries for the requested page."},"total":{"type":"integer","format":"int64","description":"Total number of entries matching the filter (across all pages)."}}},"UsageQueryParams":{"type":"object","properties":{"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"model":{"type":["string","null"],"description":"Filter by model name"},"provider":{"type":["string","null"],"description":"Filter by provider name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"UsageSource":{"type":"string","description":"How the \"actual usage\" numbers were obtained","enum":["metrics-api","requests-only","unavailable"]},"UsageSummary":{"type":"object","required":["total_requests","total_input_tokens","total_output_tokens","total_tokens","avg_latency_ms","total_cost_microcents","error_count","streaming_count","byok_count"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"byok_count":{"type":"integer","format":"int64"},"error_count":{"type":"integer","format":"int64"},"streaming_count":{"type":"integer","format":"int64"},"total_cost_microcents":{"type":"integer","format":"int64"},"total_input_tokens":{"type":"integer","format":"int64"},"total_output_tokens":{"type":"integer","format":"int64"},"total_requests":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"UserResponse":{"type":"object","required":["id","username","name","avatar_url","mfa_enabled","role"],"properties":{"avatar_url":{"type":"string"},"email":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"role":{"type":"string","description":"User's role (e.g., \"admin\", \"user\", \"demo\")"},"username":{"type":"string"}}},"ValidateEmailRequest":{"type":"object","description":"Request body for validating an email address","required":["email"],"properties":{"email":{"type":"string","description":"Email address to validate","example":"someone@gmail.com"},"proxy":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProxyRequest","description":"Optional SOCKS5 proxy configuration"}]}}},"ValidateEmailResponse":{"type":"object","description":"Complete email validation response","required":["email","is_reachable","syntax","mx","misc","smtp"],"properties":{"email":{"type":"string","description":"The email address that was validated","example":"someone@gmail.com"},"is_reachable":{"$ref":"#/components/schemas/ReachabilityStatus","description":"Overall reachability status: safe, risky, invalid, or unknown"},"misc":{"$ref":"#/components/schemas/MiscResult","description":"Miscellaneous validation result"},"mx":{"$ref":"#/components/schemas/MxResult","description":"MX record validation result"},"smtp":{"$ref":"#/components/schemas/SmtpResult","description":"SMTP validation result"},"syntax":{"$ref":"#/components/schemas/SyntaxResult","description":"Syntax validation result"}}},"ValidationLevel":{"type":"string","description":"Validation severity level","enum":["info","warning","error","critical"]},"ValidationReport":{"type":"object","description":"Complete validation report","required":["results","overall_status","summary"],"properties":{"overall_status":{"$ref":"#/components/schemas/ValidationStatus","description":"Overall status"},"results":{"type":"array","items":{"$ref":"#/components/schemas/ValidationResult"},"description":"All validation results"},"summary":{"$ref":"#/components/schemas/ValidationSummary","description":"Summary statistics"}}},"ValidationResponse":{"type":"object","required":["connection_id","is_valid","message"],"properties":{"connection_id":{"type":"integer","format":"int32"},"is_valid":{"type":"boolean"},"message":{"type":"string"}}},"ValidationResult":{"type":"object","description":"Result of a validation check","required":["rule_id","rule_name","level","passed","message","affected_resources"],"properties":{"affected_resources":{"type":"array","items":{"type":"string"},"description":"Affected resources/fields"},"level":{"$ref":"#/components/schemas/ValidationLevel","description":"Validation level"},"message":{"type":"string","description":"Message describing the result"},"passed":{"type":"boolean","description":"Whether the validation passed"},"remediation":{"type":["string","null"],"description":"Suggested remediation (if failed)"},"rule_id":{"type":"string","description":"Rule that was checked"},"rule_name":{"type":"string","description":"Human-readable rule name"}}},"ValidationStatus":{"type":"string","description":"Overall validation status","enum":["passed","passed-with-warnings","failed-with-warnings","failed"]},"ValidationSummary":{"type":"object","description":"Validation summary statistics","required":["total_count","passed_count","failed_count","info_count","warning_count","error_count","critical_count"],"properties":{"critical_count":{"type":"integer","description":"Critical-level results","minimum":0},"error_count":{"type":"integer","description":"Error-level results","minimum":0},"failed_count":{"type":"integer","description":"Validations that failed","minimum":0},"info_count":{"type":"integer","description":"Info-level results","minimum":0},"passed_count":{"type":"integer","description":"Validations that passed","minimum":0},"total_count":{"type":"integer","description":"Total validations run","minimum":0},"warning_count":{"type":"integer","description":"Warning-level results","minimum":0}}},"VerifyMfaRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"ViewItem":{"type":"object","required":["label","value"],"properties":{"label":{"type":"string","format":"date-time"},"value":{"type":"integer","format":"int64"}}},"ViewsOverTime":{"type":"object","required":["items","metric","present_index"],"properties":{"comparison_labels":{"type":["array","null"],"items":{"type":"string"}},"comparison_plot":{"type":["array","null"],"items":{"type":"integer","format":"int64"}},"full_intervals":{"type":["array","null"],"items":{"type":"string"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/ViewItem"}},"metric":{"type":"string"},"present_index":{"type":"integer","minimum":0}}},"ViewsOverTimeQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"VisitorDetails":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorFacetValue":{"type":"object","description":"A single facet value with its visitor count. Used to populate filter\ndropdowns on the visitors page (e.g. \"Germany — 1,234 visitors\").","required":["value","count"],"properties":{"code":{"type":["string","null"],"description":"Optional secondary code for the value. Currently only populated for\nthe `country` facet, where it carries the 2-letter ISO country code\nso the UI can render a flag without re-mapping."},"count":{"type":"integer","format":"int64","description":"Distinct visitor count matching this value in the current segment."},"value":{"type":"string","description":"The dimension value (e.g. \"United States\", \"Chrome\", \"google.com\").\n`None` is encoded as the literal string \"Direct\" for referrer and as\nthe empty string for the rest."}}},"VisitorFacets":{"type":"object","description":"All filter dropdown contents in one response. Each list is the top N\nvalues for that dimension within the current date range and segment\n(excluding the dimension being queried so the dropdown still shows\nalternatives when a value is already selected).","required":["country","region","city","channel","referrer"],"properties":{"channel":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"city":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"country":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"referrer":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"region":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}}}},"VisitorFacetsQuery":{"allOf":[{"$ref":"#/components/schemas/VisitorSegmentFilters"},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"has_activity_only":{"type":["boolean","null"]},"include_crawlers":{"type":["boolean","null"]},"per_facet_limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of values returned per dimension (default: 50, max: 200)."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}],"description":"Query parameters for the visitor-facets endpoint. Mirrors the shape of\n`VisitorsListQuery` so the same segment filters apply — facet counts are\nalways computed against the *currently filtered* visitor pool, minus the\ndimension being aggregated."},"VisitorInfo":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"current_page":{"type":["string","null"],"description":"Most recent page path visited by this visitor"},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorJourneyQuery":{"type":"object","required":["project_id"],"properties":{"limit_sessions":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"VisitorJourneyResponse":{"type":"object","description":"Complete visitor journey response","required":["visitor_id","total_sessions","total_events","sessions"],"properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/JourneySession"},"description":"Sessions with their events, ordered newest first"},"total_events":{"type":"integer","format":"int64","description":"Total number of events across all sessions"},"total_sessions":{"type":"integer","format":"int64","description":"Total number of sessions"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor internal ID"}}},"VisitorLocationsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"granularity":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LocationGranularity"}]},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"VisitorRecord":{"type":"object","required":["id","visitor_id","project_id","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"custom_data":{},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"visitor_id":{"type":"string"}}},"VisitorSegmentFilters":{"type":"object","description":"Optional segment filters for [`VisitorsListQuery`]. Each filter narrows the\nresult set to visitors who match the given dimension value within the date\nrange. All filters resolve against `visitor` / `ip_geolocations` — by\ndesign we never touch the events hypertable here so filtering stays fast\nregardless of event volume.","properties":{"filter_channel":{"type":["string","null"],"description":"First-touch marketing channel (matches `visitor.first_channel`)"},"filter_city":{"type":["string","null"],"description":"Geolocation city (matches `ip_geolocations.city`)"},"filter_country":{"type":["string","null"],"description":"Geolocation country (matches `ip_geolocations.country`)"},"filter_referrer":{"type":["string","null"],"description":"First-touch referrer hostname (matches `visitor.first_referrer_hostname`)"},"filter_region":{"type":["string","null"],"description":"Geolocation region (matches `ip_geolocations.region`)"}}},"VisitorSessionsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"VisitorSessionsResponse":{"type":"object","required":["visitor_id","sessions","total_sessions"],"properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionSummary"}},"total_sessions":{"type":"integer","format":"int64"},"visitor_id":{"type":"string"}}},"VisitorStats":{"type":"object","required":["visitor_id","first_seen","last_seen","total_sessions","total_page_views","total_events","average_session_duration","bounce_rate","engagement_rate","top_pages","top_referrers","devices_used","locations"],"properties":{"average_session_duration":{"type":"number","format":"double"},"bounce_rate":{"type":"number","format":"double"},"devices_used":{"type":"array","items":{"type":"string"}},"engagement_rate":{"type":"number","format":"double"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"locations":{"type":"array","items":{"$ref":"#/components/schemas/LocationInfo"}},"top_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageVisit"}},"top_referrers":{"type":"array","items":{"type":"string"}},"total_events":{"type":"integer","format":"int64"},"total_page_views":{"type":"integer","format":"int64"},"total_sessions":{"type":"integer","format":"int64"},"visitor_id":{"type":"integer","format":"int32"}}},"VisitorWithGeolocation":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorsListQuery":{"allOf":[{"$ref":"#/components/schemas/VisitorSegmentFilters"},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"has_activity_only":{"type":["boolean","null"],"description":"Filter to only include visitors with recorded activity (events/sessions).\nWhen true, excludes \"ghost\" visitors that have no events."},"include_crawlers":{"type":["boolean","null"]},"limit":{"type":["integer","null"],"format":"int32"},"offset":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"VisitorsResponse":{"type":"object","required":["visitors","total_count","filtered_count"],"properties":{"filtered_count":{"type":"integer","format":"int64"},"total_count":{"type":"integer","format":"int64"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/VisitorInfo"}}}},"VolumeMount":{"type":"object","description":"Volume mount in deployment","required":["source","destination","read_only","type"],"properties":{"destination":{"type":"string","description":"Destination path in container"},"read_only":{"type":"boolean","description":"Read-only flag"},"source":{"type":"string","description":"Source (volume name or path)"},"type":{"$ref":"#/components/schemas/VolumeType","description":"Volume type"}}},"VolumeType":{"type":"string","description":"Volume type","enum":["bind","volume","tmpfs"]},"VulnerabilityResponse":{"type":"object","required":["id","scan_id","vulnerability_id","package_name","installed_version","severity","title","created_at"],"properties":{"class":{"type":["string","null"],"example":"os-pkgs"},"created_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"cvss_score":{"type":["number","null"],"format":"float"},"description":{"type":["string","null"]},"fixed_version":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"installed_version":{"type":"string"},"last_modified_date":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"package_name":{"type":"string"},"primary_url":{"type":["string","null"]},"published_date":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"references":{},"scan_id":{"type":"integer","format":"int32"},"severity":{"type":"string"},"target":{"type":["string","null"],"example":"alpine:3.18 (alpine 3.18.0)"},"title":{"type":"string"},"type":{"type":["string","null"],"example":"alpine"},"vulnerability_id":{"type":"string"}}},"WalWarning":{"oneOf":[{"type":"object","description":"`pg_wal` is significantly larger than `max_wal_size`.","required":["pg_wal_bytes","max_wal_size_bytes","ratio","kind"],"properties":{"kind":{"type":"string","enum":["wal_bloat"]},"max_wal_size_bytes":{"type":"integer","format":"int64"},"pg_wal_bytes":{"type":"integer","format":"int64"},"ratio":{"type":"number","format":"double"}}},{"type":"object","description":"A replication slot is holding WAL it's not consuming.","required":["slot_name","retained_bytes","active","kind"],"properties":{"active":{"type":"boolean"},"kind":{"type":"string","enum":["stale_slot"]},"retained_bytes":{"type":"integer","format":"int64"},"slot_name":{"type":"string"}}},{"type":"object","description":"`archive_status/*.ready` count exceeds threshold — `archive_command`\nis either failing or running slower than WAL generation.","required":["ready_count","kind"],"properties":{"kind":{"type":"string","enum":["archive_backlog"]},"ready_count":{"type":"integer","format":"int64"}}},{"type":"object","description":"`archive_mode = on` but `archive_command` is empty / `/bin/true`.\nWAL accumulates forever waiting for a destination that never accepts.","required":["kind"],"properties":{"kind":{"type":"string","enum":["archive_mode_without_command"]}}},{"type":"object","description":"Oldest WAL segment is older than `WAL_NOT_RECYCLED_AGE_SECS`.\nIndependent signal: something is blocking recycling even if total\nsize hasn't exploded yet.","required":["oldest_age_secs","kind"],"properties":{"kind":{"type":"string","enum":["wal_not_recycled"]},"oldest_age_secs":{"type":"integer","format":"int64"}}}],"description":"One actionable warning surfaced to the UI.\n\nEach variant carries the data needed to render a remediation hint without\nthe frontend re-querying anything."},"WalWarningSeverity":{"type":"string","enum":["warning","critical"]},"WebhookConfig":{"type":"object","description":"Configuration for a generic webhook notification provider","required":["url"],"properties":{"headers":{"type":"object","description":"Custom headers to include in the request (e.g., for authentication tokens)","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"},"example":{"Authorization":"Bearer your-token","X-Custom-Header":"custom-value"}},"method":{"type":"string","description":"HTTP method to use (POST, PUT, PATCH). Defaults to POST.","example":"POST"},"timeout_secs":{"type":"integer","format":"int64","description":"Request timeout in seconds. Defaults to 30.","example":30,"minimum":0},"url":{"type":"string","description":"The URL to send webhook requests to","example":"https://api.example.com/notifications"}}},"WebhookDeliveryResponse":{"type":"object","required":["id","webhook_id","event_type","event_id","payload","success","attempt_number","created_at"],"properties":{"attempt_number":{"type":"integer","format":"int32"},"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"delivered_at":{"type":["string","null"],"format":"date-time"},"error_message":{"type":["string","null"]},"event_id":{"type":"string"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int32"},"payload":{"type":"string","description":"JSON payload that was sent to the webhook endpoint","example":{"event_type":"deployment.succeeded","data":{"deployment_id":123}}},"status_code":{"type":["integer","null"],"format":"int32"},"success":{"type":"boolean"},"webhook_id":{"type":"integer","format":"int32"}}},"WebhookResponse":{"type":"object","required":["id","project_id","url","events","enabled","has_secret","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"enabled":{"type":"boolean"},"events":{"type":"array","items":{"type":"string"}},"has_secret":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"url":{"type":"string"}}},"WebhookTriggerRequest":{"allOf":[{"description":"Arbitrary JSON payload from the caller. Passed to the agent as user_context."}]},"WebhookTriggerResponse":{"type":"object","required":["run_id","status"],"properties":{"run_id":{"type":"integer","format":"int32"},"status":{"type":"string"}}},"WorkflowDryRunRequest":{"type":"object","required":["yaml"],"properties":{"cpu_limit":{"type":["number","null"],"format":"double","description":"Optional CPU override applied after parsing YAML (clamped server-side).\nWhen `Some`, this takes precedence over `cpu_limit` inside the YAML —\nlets the CLI pass `--cpu` without rewriting the YAML text."},"error_group_id":{"type":["integer","null"],"format":"int32","description":"Optional error group to link this dry-run to. When set, the executor's\n`load_error_context` path injects `{{error_type}}` / `{{error_message}}`\n/ `{{stack_trace}}` into the prompt — same behaviour as a committed\nworkflow triggered with `trigger_source_type = \"error_group\"`. Must\nbelong to `project_id` (handler enforces)."},"memory_limit_mb":{"type":["integer","null"],"format":"int64","description":"Optional memory override in MB (clamped server-side). Same precedence\nrule as `cpu_limit`.","minimum":0},"user_context":{"type":["string","null"],"description":"Optional context appended to the prompt (e.g. \"test against staging\nonly\"). Mirrors `TriggerAgentRequest.user_context`."},"yaml":{"type":"string","description":"Full WorkflowYamlConfig as YAML text. Server validates and re-serializes\nbefore storing on the run row."}}},"WorkloadDescriptor":{"type":"object","description":"Brief descriptor for discovered workloads (used in listing)","required":["id","workload_type","status","labels"],"properties":{"created_at":{"type":["string","null"],"format":"date-time","description":"Creation timestamp"},"id":{"$ref":"#/components/schemas/WorkloadId","description":"Unique ID in source system"},"image":{"type":["string","null"],"description":"Image/build reference (for containers)"},"labels":{"type":"object","description":"Labels/tags from source system","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":["string","null"],"description":"Workload name (if any)"},"status":{"$ref":"#/components/schemas/WorkloadStatus","description":"Current status"},"workload_type":{"$ref":"#/components/schemas/WorkloadType","description":"Workload type (container, function, static-site, etc.)"}}},"WorkloadId":{"type":"string","description":"Unique identifier for a workload in the source system"},"WorkloadStatus":{"type":"string","description":"Workload status in source system","enum":["running","paused","stopped","exited","failed","deployed","building","unknown"]},"WorkloadType":{"type":"string","description":"Workload type","enum":["container","function","static-site","server-side-app","worker","database","message-queue","cache","cron-job","other"]},"WriteFileBody":{"type":"object","required":["path","contents_b64"],"properties":{"contents_b64":{"type":"string","description":"File contents, base64-encoded. Required — lets callers ship binary\ndata over JSON without charset games."},"mode":{"type":["integer","null"],"format":"int32","description":"Unix permission mask (e.g. 0o644). Defaults to 0o644 when absent.","minimum":0},"path":{"type":"string","description":"Absolute path inside the sandbox. Must start with `/`."}},"additionalProperties":false},"WriteFilesBody":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/WriteFileBody"},"description":"List of files to write. Each entry must include an absolute\n`path` and base64-encoded `contents_b64`. Empty list is a no-op."}},"additionalProperties":false},"WriteFilesResponse":{"type":"object","required":["written"],"properties":{"written":{"type":"integer","description":"Number of files successfully written before the first failure\n(if any). On full success this equals `files.len()`.","minimum":0}}},"ZoneListResponse":{"type":"object","description":"Zone list response","required":["zones"],"properties":{"zones":{"type":"array","items":{"$ref":"#/components/schemas/DnsZone"}}}}},"securitySchemes":{"bearer_auth":{"type":"http","scheme":"bearer","description":"Bearer token authentication. Use format: `Bearer `. Supports API keys (starting with `tk_`), CLI tokens, and session tokens."}}},"tags":[{"name":"Events","description":"Analytics events tracking endpoints"},{"name":"Metrics","description":"Analytics metrics collection endpoints including performance web vitals"},{"name":"Funnels","description":"Funnel management endpoints"},{"name":"Analytics","description":"Analytics and session replay management"},{"name":"Performance","description":"Performance metrics management"},{"name":"geo","description":"Geolocation API endpoints"},{"name":"Platform","description":"Platform information and compatibility"},{"name":"Git Providers","description":"Git provider management endpoints"},{"name":"Repositories","description":"Repository management endpoints"},{"name":"Public Repositories","description":"Endpoints for accessing public repositories without authentication. Supports GitHub and GitLab."},{"name":"Notification Providers","description":"Notification provider management endpoints"},{"name":"Notification Preferences","description":"User notification preferences and settings"},{"name":"DNS Providers","description":"DNS provider management endpoints"},{"name":"Internal DNS","description":"Per-node DNS resolver sync (ADR-011)"},{"name":"Domains","description":"Domain management endpoints"},{"name":"Email Providers","description":"Email provider management endpoints"},{"name":"Email Domains","description":"Email domain management and verification"},{"name":"Emails","description":"Email sending and retrieval"},{"name":"Email Tracking","description":"Email open and click tracking"},{"name":"Email Validation","description":"Email address validation and verification"},{"name":"Webhooks","description":"Webhook management endpoints"},{"name":"Webhook Deliveries","description":"Webhook delivery history and retry endpoints"},{"name":"External Services","description":"External service integration endpoints"},{"name":"External Services - Query","description":"Data querying and exploration endpoints"},{"name":"Metrics","description":"Time-series metrics and alert rule endpoints"},{"name":"KV Store","description":"Key-Value storage operations"},{"name":"KV Management","description":"KV service management operations"},{"name":"Blob","description":"Blob storage operations"},{"name":"Blob Management","description":"Blob service management operations"},{"name":"Feature Flags","description":"Runtime configuration that changes without a redeploy"},{"name":"Environments","description":"Environment management operations"},{"name":"Secrets","description":"File-mounted secrets (/run/secrets/)"},{"name":"Projects","description":"Project management endpoints"},{"name":"Presets","description":"Available deployment presets"},{"name":"Templates","description":"Project template endpoints"},{"name":"Custom Domains","description":"Custom domain management for projects"},{"name":"error-tracking","description":"Error tracking data fetching endpoints"},{"name":"Vulnerability Scans","description":"Vulnerability scan management endpoints"},{"name":"Agents","description":"Autonomous AI agents, autofixer (interactive AI debugging), skills/MCP definitions, and preview gateway management."},{"name":"Crons","description":"Cron jobs management API"},{"name":"Sandboxes","description":"Standalone sandbox API (`/v1/sandboxes/*`) for running isolated containers."},{"name":"Logs","description":"Log search, context, live tail, and retention management"},{"name":"Imports","description":"Import workloads from external sources"},{"name":"Status Page","description":"Status page and monitoring endpoints"},{"name":"OTel Ingest","description":"OTLP/HTTP ingest endpoints (protobuf)"},{"name":"OTel","description":"Query endpoints for the monitoring UI"},{"name":"GenAI","description":"GenAI agent activity tracing endpoints"},{"name":"Alarms","description":"Unified alarm history — list, summarise, acknowledge, resolve"},{"name":"Authentication","description":"Authentication and authorization endpoints"},{"name":"Users","description":"User management endpoints"},{"name":"Backups","description":"Backup management endpoints"},{"name":"Restore","description":"External service restore operations"},{"name":"Revenue","description":"Per-project revenue tracking integrations and analytics"},{"name":"Observability","description":"Unified observability event stream — runtime logs, requests, spans, errors, revenue"},{"name":"AI Gateway","description":"OpenAI-compatible chat, embeddings, and model endpoints"},{"name":"AI Gateway Admin","description":"Provider key management endpoints"},{"name":"AI Gateway Usage","description":"Usage analytics and reporting endpoints"},{"name":"AI Gateway Pricing","description":"Model pricing endpoints"},{"name":"API Keys","description":"API key management endpoints"},{"name":"Load Balancer","description":"Load balancer management endpoints"},{"name":"IP Access Control","description":"IP access control management endpoints"},{"name":"Files","description":"Static file serving endpoints"},{"name":"External Plugins","description":"External plugin management and discovery"}]} diff --git a/apps/temps-cli/scripts/generate-docs.ts b/apps/temps-cli/scripts/generate-docs.ts index a7538430e..5d5db62d6 100644 --- a/apps/temps-cli/scripts/generate-docs.ts +++ b/apps/temps-cli/scripts/generate-docs.ts @@ -29,6 +29,7 @@ import { registerApiKeysCommands } from '../src/commands/apikeys/index.js' import { registerMonitorsCommands } from '../src/commands/monitors/index.js' import { registerWebhooksCommands } from '../src/commands/webhooks/index.js' import { registerContainersCommands } from '../src/commands/containers/index.js' +import { registerFlagsCommands } from '../src/commands/flags/index.js' interface CommandInfo { name: string @@ -300,6 +301,7 @@ async function main() { registerMonitorsCommands(program) registerWebhooksCommands(program) registerContainersCommands(program) +registerFlagsCommands(program) // Extract command information const commands: CommandInfo[] = program.commands.map((cmd: Command) => diff --git a/apps/temps-cli/src/api/index.ts b/apps/temps-cli/src/api/index.ts index 4cd01fd65..ce92a2747 100644 --- a/apps/temps-cli/src/api/index.ts +++ b/apps/temps-cli/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobHead, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, rebuildSandboxImage, recordConsoleEvent, recordEventMetrics, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, sendMessage, setDefaultS3Source, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, streamEvents, streamRunEvents, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from './sdk.gen'; -export type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, AcmeOrderResponse, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponse, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponse, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponse, ActivateProviderResponses, ActiveVisitor, ActiveVisitorsQuery, ActiveVisitorsResponse, ActivityDay, ActivityEvent, ActivityGraphQuery, ActivityGraphResponse, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberRequest, AddClusterMemberResponse, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextRequest, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainRequest, AddEnvironmentDomainResponse, AddEnvironmentDomainResponses, AddEventsData, AddEventsError, AddEventsErrors, AddEventsRequest, AddEventsResponse, AddEventsResponse2, AddEventsResponses, AddManagedDomainApiRequest, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponse, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsErrors, AddSessionReplayEventsResponse, AddSessionReplayEventsResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponse, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponse, AdminDrainStatusResponses, AdminGateResponse, AdminGateSource, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponse, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponse, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponse, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponse, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponse, AdminUndrainNodeResponses, AgentConfigResponse, AgentRunLogResponse, AgentRunResponse, AgentRunWithLogsResponse, AgentSandboxSettings, AgentSandboxSettingsMasked, AggregatedBucketItem, AggregatedBucketsQuery, AggregatedBucketsResponse, AggregationLevel, AggregationTemporality, AiAgentBreakdownResponse, AiAgentBreakdownRow, AiAgentDescriptor, AiAgentPageRow, AiAgentPagesResponse, AiAgentTimelineResponse, AiAgentTimelineRow, AiConfigSettings, AiPageBreakdownResponse, AiPageBreakdownRow, AiStatusBreakdownResponse, AiStatusBreakdownRow, AlarmListResponse, AlarmResponse, AlarmSummaryResponse, AlertRuleResponse, AllocEntry, AnalyticsSessionEventsResponse, AnnotatedSpan, AnomalyAlgorithm, AnomalyParams, AnomalyPreviewPointResponse, AnomalyPreviewRequest, AnomalyPreviewResponse, ApiKeyListResponse, ApiKeyResponse, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeRequest, ApplyHostnameModeResponse, ApplyHostnameModeResponses, AppSettings, AppSettingsResponse, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponse, ArchiveConversationResponses, ArchiveMode, AssignRoleData, AssignRoleErrors, AssignRoleRequest, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesErrors, AttachScheduleServicesRequest, AttachScheduleServicesResponse, AttachScheduleServicesResponse2, AttachScheduleServicesResponses, AuditLogIpInfo, AuditLogResponse, AuditLogUserInfo, AuthFlavorDto, AuthResponse, AuthStatusResponse, AuthTokenResponse, AutofixerRunResponse, AutofixerRunWithLogsResponse, AutofixRunConfig, AutoWatchParams, AvailableContainerInfo, AvailablePermissions, BackupAlertListResponse, BackupAlertResponse, BackupResponse, BackupScheduleResponse, BitbucketAuthInput, BlobCopyData, BlobCopyError, BlobCopyErrors, BlobCopyResponse, BlobCopyResponses, BlobDeleteData, BlobDeleteError, BlobDeleteErrors, BlobDeleteResponse, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponse, BlobDisableResponses, BlobDownloadData, BlobDownloadError, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponse, BlobEnableResponses, BlobHeadData, BlobHeadError, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListError, BlobListErrors, BlobListResponse, BlobListResponses, BlobPutData, BlobPutError, BlobPutErrors, BlobPutResponse, BlobPutResponses, BlobResponse, BlobStatusData, BlobStatusErrors, BlobStatusResponse, BlobStatusResponse2, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponse, BlobUpdateResponses, BranchInfo, BranchListResponse, BrowserCount, BrowsersQuery, BuildConfiguration, BuildLimitsSettings, CancelBackupData, CancelBackupError, CancelBackupErrors, CancelBackupResponse, CancelBackupResponse2, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponse, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponse, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponse, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponse, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunErrors, CancelScheduleRunResponse, CancelScheduleRunResponses, CertStatusResponse, ChallengeConfig, ChallengeError, ChallengeValidationStatus, ChangePasswordRequest, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponse, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceRequest, ChangeProjectSourceResponse, ChangeProjectSourceResponses, ChatCompletionChoice, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsErrors, ChatCompletionsResponse, ChatCompletionsResponses, ChatMessage, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponse, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponse, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponse, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponse, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedError, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponse, CheckProviderDeletionSafetyResponses, ChildBackupEntryResponse, ChildBackupListResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsErrors, CleanupExpiredBackupsRequest, CleanupExpiredBackupsResponse, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponse, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveRequest, CliDeviceApproveResponse, CliDeviceApproveResponse2, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponse, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponse, CliDeviceLookupResponse2, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollRequest, CliDevicePollResponse, CliDevicePollResponse2, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartRequest, CliDeviceStartResponse, CliDeviceStartResponse2, CliDeviceStartResponses, ClientOptions, CliLoginRequest, CliLogoutData, CliLogoutErrors, CliLogoutResponse, CliLogoutResponses, CloudflareConfig, CloudProvider, ClusterCapacity, ClusterDnsSettings, ClusterHealthReportResponse, ClusterMemberHealthResponse, ClusterMemberRequest, CmdBody, CmdData, CmdErrors, CmdInner, CmdKillBody, CmdKillData, CmdKillErrors, CmdKillResponse, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponse, CmdResponse2, CmdResponses, CommitExistsResponse, CommitInfo, CommitListResponse, Comparator, ComposePublicPort, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponse, ConfirmPendingActionResponses, ConnectionListQuery, ConnectionListResponse, ConnectionResponse, ConnectionTestResult, ConsoleEventPayload, ContainerActionResponse, ContainerDetailResponse, ContainerEnvironmentVariableValueResponse, ContainerInfoResponse, ContainerInventoryItem, ContainerListResponse, ContainerLogSettings, ContainerLogsQuery, ContainerMetricHistoryPoint, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponse, ContainerMetricsGetHistoryResponses, ContainerMetricsHistoryQuery, ContainerMetricsResponse, ContainerResponse, ContainerRuntimeInfo, ContainerStatsSample, ContentPart, ContextLine, ContextLogsRequest, ContextLogsResponse, ConversationDetailResponse, ConversationResponse, ConversationsQueryParams, ConversationSummary, CopyBlobRequest, CostAnalysis, CreateAgentData, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAlertData, CreateAlertError, CreateAlertErrors, CreateAlertResponse, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleRequest, CreateAlertRuleResponse, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyRequest, CreateApiKeyResponse, CreateApiKeyResponse2, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleErrors, CreateBackupScheduleRequest, CreateBackupScheduleResponse, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponse, CreateBitbucketProviderResponses, CreateBitbucketRequest, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderRequest, CreateCloudflareProviderResponse, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationRequest, CreateConversationResponse, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponse, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardError, CreateDashboardErrors, CreateDashboardRequest, CreateDashboardResponse, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenRequest, CreateDeploymentTokenResponse, CreateDeploymentTokenResponse2, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderRequest, CreateDnsProviderResponse, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainRequest, CreateDomainResponse, CreateDomainResponses, CreatedResource, CreateDsnData, CreateDsnErrors, CreateDsnRequest, CreateDsnResponse, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainRequest, CreateEmailDomainResponse, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderRequest, CreateEmailProviderResponse, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentRequest, CreateEnvironmentResponse, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableRequest, CreateEnvironmentVariableResponse, CreateEnvironmentVariableResponses, CreateExternalServiceRequest, CreateFunnelData, CreateFunnelErrors, CreateFunnelRequest, CreateFunnelResponse, CreateFunnelResponse2, CreateFunnelResponses, CreateFunnelStep, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponse, CreateGenericProviderResponses, CreateGenericRequest, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponse, CreateGiteaPatProviderResponses, CreateGiteaPatRequest, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponse, CreateGithubPatProviderResponses, CreateGitHubPatRequest, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponse, CreateGitlabOauthProviderResponses, CreateGitLabOAuthRequest, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponse, CreateGitlabPatProviderResponses, CreateGitLabPatRequest, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponse, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponse, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponse, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentRequest, CreateIncidentResponse, CreateIncidentResponses, CreateIntegrationBody, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlErrors, CreateIpAccessControlRequest, CreateIpAccessControlResponse, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpRequest, CreateMcpResponse, CreateMcpResponses, CreateMetricAlertRequest, CreateMonitorData, CreateMonitorErrors, CreateMonitorRequest, CreateMonitorResponse, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderRequest, CreateNotificationEmailProviderResponse, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponse, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderRequest, CreateOidcProviderResponse, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingRequest, CreateOidcRoleMappingResponse, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponse, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanRequest, CreatePlanResponse, CreatePlanResponse2, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateRequest, CreateProjectFromTemplateResponse, CreateProjectFromTemplateResponse2, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponse, CreateProjectReleaseResponses, CreateProjectRequest, CreateProjectResponse, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretRequest, CreateProjectSecretResponse, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyErrors, CreateProviderKeyRequest, CreateProviderKeyResponse, CreateProviderKeyResponses, CreateProviderRequest, CreatePrResponse, CreatePrResponse2, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponse, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteRequest, CreateRouteResponse, CreateRouteResponses, CreateS3SourceData, CreateS3SourceError, CreateS3SourceErrors, CreateS3SourceRequest, CreateS3SourceResponse, CreateS3SourceResponses, CreateSandboxBody, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponse, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponse, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillRequest, CreateSkillResponse, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderRequest, CreateSlackProviderResponse, CreateSlackProviderResponses, CreateUserData, CreateUserErrors, CreateUserRequest, CreateUserResponse, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderRequest, CreateWebhookProviderResponse, CreateWebhookProviderResponses, CreateWebhookRequestBody, CreateWebhookResponse, CreateWebhookResponses, CronExecutionInfo, CronInfo, CrossProjectSiblingRef, CrossProjectTraceResponse, CurrentStatusResponse, CustomDomainRequest, CustomDomainResponse, CustomerMovementResponse, DashboardLayout, DashboardProjectsAnalyticsQuery, DashboardProjectsAnalyticsResponse, DashboardSection, DashboardTile, DatabaseMetricsResponse, DatabaseMetricsRow, DataImplication, DataImplicationSeverity, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponse, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAlertData, DeleteAlertError, DeleteAlertErrors, DeleteAlertResponse, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponse, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponse, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupError, DeleteBackupErrors, DeleteBackupResponse, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleErrors, DeleteBackupScheduleResponse, DeleteBackupScheduleResponses, DeleteBlobRequest, DeleteBlobResponse, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponse, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponse, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardError, DeleteDashboardErrors, DeleteDashboardResponse, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponse, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponse, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponse, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponse, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponse, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponse, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponse, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponse, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponse, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponse, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponse, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlErrors, DeleteIpAccessControlResponse, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponse, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponse, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponse, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponse, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponse, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyErrors, DeleteProviderKeyResponse, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponse, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponse, DeleteReleaseSourceMapsResponses, DeleteResponse, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponse, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceErrors, DeleteS3SourceResponse, DeleteS3SourceResponses, DeleteScanData, DeleteScanError, DeleteScanErrors, DeleteScanResponse, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponse, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponse, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponse, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponse, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponse, DeleteStaticBundleResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponse, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponse, DeleteWebhookResponses, DelRequest, DelResponse, DeployFromImageData, DeployFromImageErrors, DeployFromImageRequest, DeployFromImageResponse, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadQuery, DeployFromImageUploadResponse, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticRequest, DeployFromStaticResponse, DeployFromStaticResponses, DeploymentConfig, DeploymentConfigSnapshot, DeploymentConfiguration, DeploymentContainerLogContentResponse, DeploymentContainerLogResponse, DeploymentContainerLogsListResponse, DeploymentEnvironmentResponse, DeploymentJobResponse, DeploymentJobsResponse, DeploymentListResponse, DeploymentMetadata, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponse, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DeploymentResponse, DeploymentStateResponse, DeploymentStrategy, DeploymentTokenListResponse, DeploymentTokenResponse, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponse, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceErrors, DetachScheduleServiceResponse, DetachScheduleServiceResponses, DetectionConfig, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponse, DetectPublicPresetsResponses, DeviceCount, DigestSections, Direction, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponse, DisableBackupScheduleResponses, DisableBlobResponse, DisableKvResponse, DisableMfaData, DisableMfaErrors, DisableMfaRequest, DisableMfaResponse, DisableMfaResponses, DiscoverRequest, DiscoverResponse, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponse, DiscoverWorkloadsResponses, DiskInfo, DiskSpaceAlert, DiskSpaceAlertSettings, DiskSpaceCheckResult, DnsAckRequest, DnsAckResponse, DnsChallengeRecordResult, DnsChangesResponse, DnsCompletionResponse, DnsLookupError, DnsLookupRequest, DnsLookupResponse, DnsProviderCredentials, DnsProviderResponse, DnsProviderSettings, DnsProviderSettingsMasked, DnsProviderType, DnsRecord, DnsRecordChange, DnsRecordContent, DnsRecordResponse, DnsRecordSetupResult, DnsRecordStatusResponse, DnsZone, DockerComposePresetConfig, DockerfilePresetConfig, DockerfileVariant, DockerRegistrySettings, DockerRegistrySettingsMasked, DomainAction, DomainChallengeResponse, DomainData, DomainEnvironmentResponse, DomainError, DomainErrors, DomainPlan, DomainResponse, DomainResponse2, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponse, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponse, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponse, DownloadSkillArchiveResponses, DrainNodeResponse, DrainStatusResponse, DropOffPoint, EmailConfig, EmailDomainResponse, EmailDomainWithDnsResponse, EmailProviderResponse, EmailProviderTypeRoute, EmailRequest, EmailResponse, EmailStatsResponse, EmailStatusData, EmailStatusErrors, EmailStatusResponse, EmailStatusResponse2, EmailStatusResponses, EmailTrackingResponse, EmailTrackingSetupResponse, EmailTrackingStatusResponse, EmbeddingData, EmbeddingInput, EmbeddingRequest, EmbeddingResponse, EmbeddingsData, EmbeddingsError, EmbeddingsErrors, EmbeddingsResponse, EmbeddingsResponses, EmbeddingUsage, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponse, EnableBackupScheduleResponses, EnableBlobRequest, EnableBlobResponse, EnableKvRequest, EnableKvResponse, EnablePgStatStatementsResponse, EndpointDto, EnqueuedJob, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorRequest, EnrichVisitorResponse, EnrichVisitorResponse2, EnrichVisitorResponses, EnrollmentTokenInfo, EnrollmentTokenListResponse, EntityInfoResponse, EntityResponse, EnvironmentConfiguration, EnvironmentDomainResponse, EnvironmentInfo, EnvironmentResponse, EnvironmentVariable, EnvironmentVariableInfo, EnvironmentVariableResponse, EnvironmentVariableValueResponse, EnvVarInput, EnvVarIntegrationInfo, EnvVarResponse, EnvVarTemplateResponse, ErrorDashboardStatsQuery, ErrorDashboardStatsResponse, ErrorEventResponse, ErrorGroupResponse, ErrorGroupStatsResponse, ErrorResponse, ErrorRow, ErrorTimeSeriesDataResponse, ErrorTimeSeriesQuery, EventActivityBucket, EventBreakdown, EventBrowserStats, EventCount, EventCountryStats, EventDetailQuery, EventDetailResponse, EventEntriesQuery, EventEntriesResponse, EventEntryInfo, EventKind, EventMetricsPayload, EventReferrerStats, EventsCountQuery, EventsResponse, EventTimeline, EventTimelineQuery, EventType, EventTypeBreakdown, EventTypeBreakdownQuery, EventTypeResponse, EventTypesResponse, EventVisitorInfo, EventVisitorsQuery, EventVisitorsResponse, ExecBody, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponse, ExecDetachedResponse2, ExecDetachedResponses, ExecErrors, ExecResponse, ExecResponse2, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponse, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportRequest, ExecuteImportResponse, ExecuteImportResponse2, ExecuteImportResponses, ExecuteOperationRequest, ExpireRequest, ExpireResponse, ExplorerSupportResponse, ExtendTimeoutBody, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponse, ExtendTimeoutResponses, ExternalImageResponse, ExternalServiceBackupResponse, ExternalServiceDetails, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceInfo, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceSummary, FieldResponse, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponse, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponse, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponse, FindConversationResponses, FiringSeriesEntry, ForecastAlgorithm, ForecastParams, FullError, FullEvent, FullRequest, FunnelMetricsResponse, FunnelResponse, GatewayStatus, GenAiEvent, GenAiSpanDetail, GenAiTraceDetailResponse, GenAiTraceSummariesResponse, GenAiTraceSummary, GeneralStatsQuery, GeneralStatsResponse, GenerateDockerfileRequest, GenerateDockerfileResponse, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponse, GenerateJoinTokenResponse2, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponse, GeneratePresetDockerfileResponses, GeoLocationResponse, GeoRestrictionsConfig, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponse, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponse, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponse, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponse, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponse, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponse, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesErrors, GetAiAgentPagesResponse, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineErrors, GetAiAgentTimelineResponse, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownErrors, GetAiPageBreakdownResponse, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponse, GetAiStatusBreakdownResponses, GetAlertData, GetAlertError, GetAlertErrors, GetAlertResponse, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponse, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponse, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponse, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponse, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponse, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponse, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponse, GetApiKeyPermissionsResponses, GetApiKeyResponse, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponse, GetAuditLogResponses, GetBackupData, GetBackupError, GetBackupErrors, GetBackupResponse, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponse, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponse, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponse, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponse, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponse, GetChallengeTokenResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponse, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponse, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponse, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponse, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponse, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponse, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponse, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailErrors, GetConversationDetailResponse, GetConversationDetailResponses, GetConversationErrors, GetConversationResponse, GetConversationResponses, GetConversationsData, GetConversationsError, GetConversationsErrors, GetConversationsResponse, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponse, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponse, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponse, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponse, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponse, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponse, GetCustomDomainResponses, GetDashboardData, GetDashboardError, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponse, GetDashboardProjectsAnalyticsResponses, GetDashboardResponse, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponse, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponse, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponse, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponse, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponse, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponse, GetDeploymentOperationStatusResponses, GetDeploymentResponse, GetDeploymentResponses, GetDeploymentsParams, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponse, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponse, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponse, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponse, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponse, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponse, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponse, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponse, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponse, GetDomainOrderResponses, GetDomainResponse, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponse, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponse, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponse, GetEmailProviderResponses, GetEmailResponse, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponse, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponse, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponse, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponse, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponse, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponse, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponse, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponse, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesQuery, GetEnvironmentVariablesResponse, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponse, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponse, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponse, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponse, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponse, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponse, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponse, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponse, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponse, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponse, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponse, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponse, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponse, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponse, GetFileResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsQuery, GetFunnelMetricsResponse, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceErrors, GetGenaiTraceResponse, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponse, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponse, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponse, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponse, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponse, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponse, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponse, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponse, GetGroupedPageMetricsResponses, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponse, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponse, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponse, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponse, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponse, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlErrors, GetIpAccessControlResponse, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationErrors, GetIpGeolocationResponse, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponse, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponse, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanError, GetLatestScanErrors, GetLatestScanResponse, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponse, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponse, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextError, GetLogContextErrors, GetLogContextResponse, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponse, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeErrors, GetMetricsOverTimeResponse, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponse, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponse, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponse, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnRequest, GetOrCreateDsnResponse, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponse, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponse, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponse, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponse, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponse, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponse, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponse, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsErrors, GetPerformanceMetricsResponse, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponse, GetPgUpgradeLogsResponses, GetPgUpgradeResponse, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsErrors, GetPipelineStatsResponse, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponse, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponse, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponse, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingError, GetPricingErrors, GetPricingResponse, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponse, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponse, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponse, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponse, GetProjectResponses, GetProjectsData, GetProjectSecretsQuery, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponse, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysErrors, GetProjectSessionReplaysQuery, GetProjectSessionReplaysResponse, GetProjectSessionReplaysResponse2, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthErrors, GetProjectsHealthResponse, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponse, GetProjectsMonitorHealthResponses, GetProjectsResponse, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponse, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponse, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponse, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponse, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponse, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponse, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponse, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdErrors, GetProxyLogByIdResponse, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponse, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsError, GetProxyLogsErrors, GetProxyLogsResponse, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponse, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponse, GetPublicRepositoryResponses, GetQuotaData, GetQuotaError, GetQuotaErrors, GetQuotaResponse, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponse, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponse, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponse, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponse, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponse, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponse, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponse, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponse, GetRepositoryTagsResponses, GetRequest, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponse, GetResolvedEnvironmentVariableValueResponses, GetResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponse, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunError, GetRestoreRunErrors, GetRestoreRunResponse, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponse, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponse, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponse, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponse, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceError, GetS3SourceErrors, GetS3SourceResponse, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponse, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponse, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentErrors, GetScanByDeploymentResponse, GetScanByDeploymentResponses, GetScanData, GetScanError, GetScanErrors, GetScanResponse, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponse, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponse, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponse, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponse, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponse, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponse, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponse, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponse, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponse, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponse, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponse, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayError, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsErrors, GetSessionReplayEventsResponse, GetSessionReplayEventsResponses, GetSessionReplayResponse, GetSessionReplayResponse2, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponse, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponse, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponse, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponse, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponse, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponse, GetTagsByRepositoryIdResponses, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsErrors, GetTimeBucketStatsResponse, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsError, GetTodayStatsErrors, GetTodayStatsResponse, GetTodayStatsResponses, GetTraceData, GetTraceError, GetTraceErrors, GetTraceResponse, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceErrors, GetUnifiedTraceResponse, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponse, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsQuery, GetUniqueEventsResponse, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponse, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponse, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderErrors, GetUsageByProviderResponse, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentError, GetUsageRecentErrors, GetUsageRecentResponse, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryErrors, GetUsageSummaryResponse, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesErrors, GetUsageTimeseriesResponse, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsErrors, GetUsageTopModelsResponse, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponse, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponse, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponse, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponse, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponse, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponse, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsErrors, GetVisitorSessionsQuery, GetVisitorSessionsResponse, GetVisitorSessionsResponse2, GetVisitorSessionsResponses, GetVisitorsResponse, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponse, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponse, GetWebhookResponses, GitPushEvent, GitRefResponse, GitSourcePlan, GlobalConversationResponse, GlobalEventStatsResponse, GlobalMrrResponse, GlobalRecentEventResponse, GlobalRevenueSummaryResponse, GroupedPageMetric, GroupedPageMetricsQuery, GroupedPageMetricsResponse, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponse, HasAnalyticsEventsResponse2, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponse, HasErrorGroupsResponse2, HasErrorGroupsResponses, HasEventsQuery, HasEventsResponse, HasMetricsQuery, HasMetricsResponse, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsErrors, HasPerformanceMetricsResponse, HasPerformanceMetricsResponses, HealthCheckConfiguration, HealthCheckEntryResponse, HealthResponse, HealthStatus, HealthSummary, HeartbeatApiRequest, HeartbeatResponse, HierarchyLevel, HistogramSummary, HostnameChange, HostnamePreviewResponse, HourlyPageSessions, HourlyVisitsQuery, HttpChallengeDebugResponse, ImportCredentials, ImportExecutionStatus, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceRequest, ImportExternalServiceResponse, ImportExternalServiceResponses, ImportOutcomeResponse, ImportPlan, ImportRowErrorResponse, ImportSelector, ImportSource, ImportSourceCapabilities, ImportSourceInfo, ImportStatusResponse, IncidentBucket, IncidentBucketedResponse, IncidentResponse, IncidentUpdateResponse, IncrRequest, IncrResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsError, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsError, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponse, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathError, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesError, IngestTracesErrors, IngestTracesResponses, InitAuthResponse, InitSessionReplayData, InitSessionReplayError, InitSessionReplayErrors, InitSessionReplayResponse, InitSessionReplayResponses, Insight, InsightSeverity, InsightsResponse, InsightStatus, IntegrationResponse, IpAccessControlQuery, IpAccessControlResponse, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponse, JobStatusResponse2, JobStatusResponses, JobSummaryResponse, JoinTokenStatusResponse, JourneyEvent, JourneySession, KeysRequest, KeysResponse, KillJobBody, KillJobData, KillJobErrors, KillJobResponse, KillJobResponses, KnownAiAgentsResponse, KvDelData, KvDelErrors, KvDelResponse, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponse, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponse, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponse, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponse, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponse, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponse, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponse, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponse, KvStatusResponse2, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponse, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponse, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponse, LatestRunForSourceResponses, LemonSqueezyConfig, LetsEncryptSettings, LineContext, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponse, LinkCustomDomainToCertificateResponses, LinkServiceRequest, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponse, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponse, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponse, ListAgentsResponse2, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponse, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponse, ListAlertRulesResponses, ListAlertsData, ListAlertsError, ListAlertsErrors, ListAlertsResponse, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponse, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponse, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysQuery, ListApiKeysResponse, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsQuery, ListAuditLogsResponse, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponse, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsErrors, ListBackupAlertsResponse, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenErrors, ListBackupChildrenResponse, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesErrors, ListBackupSchedulesResponse, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponse, ListBackupsForScheduleResponses, ListBlobsQuery, ListBlobsResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponse, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponse, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponse, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponse, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponse, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponse, ListCustomDomainsForProjectResponses, ListCustomDomainsResponse, ListDashboardsData, ListDashboardsError, ListDashboardsErrors, ListDashboardsResponse, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponse, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensQuery, ListDeploymentTokensResponse, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponse, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponse, ListDomainsResponse2, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponse, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponse, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponse, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponse, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesQuery, ListEntitiesResponse, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsQuery, ListErrorEventsResponse, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsQuery, ListErrorGroupsResponse, ListErrorGroupsResponses, ListEventsData, ListEventsResponse, ListEventsResponses, ListEventTypesData, ListEventTypesResponse, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponse, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponse, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponse, ListExternalServiceBackupsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponse, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponse, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponse, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponse, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsError, ListInsightsErrors, ListInsightsResponse, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlErrors, ListIpAccessControlResponse, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponse, ListJobsResponse2, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsErrors, ListKnownAiAgentsResponse, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponse, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponse, ListMcpsResponse2, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysErrors, ListMetricLabelKeysResponse, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesErrors, ListMetricLabelValuesResponse, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesError, ListMetricNamesErrors, ListMetricNamesResponse, ListMetricNamesResponses, ListModelsData, ListModelsError, ListModelsErrors, ListModelsResponse, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponse, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponse, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponse, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponse, ListOnDemandCertsResponse2, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponse, ListOrdersResponse2, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponse, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponse, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponse, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponse, ListPresetsResponse2, ListPresetsResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponse, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansError, ListProjectScansErrors, ListProjectScansResponse, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponse, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponse, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponse, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponse, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysError, ListProviderKeysErrors, ListProviderKeysResponse, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponse, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponse, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponse, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponse, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponse, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponse, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponse, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponse, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponse, ListRoutesResponses, ListRunsResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesErrors, ListS3SourcesResponse, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponse, ListSandboxesResponse2, ListSandboxesResponses, ListScansQuery, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsErrors, ListScheduleRunJobsResponse, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsErrors, ListScheduleRunsResponse, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesErrors, ListScheduleServicesResponse, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponse, ListSecretsResponse2, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponse, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponse, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesErrors, ListServiceSchedulesResponse, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponse, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponse, ListSkillsResponse2, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsErrors, ListSourceBackupsResponse, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponse, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponse, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponse, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponse, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponse, ListSyncedRepositoriesResponses, ListTagsResponse, ListTemplatesQuery, ListTemplatesResponse, ListUsersData, ListUsersErrors, ListUsersResponse, ListUsersResponses, ListVulnerabilitiesQuery, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponse, ListWebhooksResponses, LiveVisitorInfo, LiveVisitorsListResponse, LocationCount, LocationGranularity, LocationInfo, LoginData, LoginErrors, LoginRequest, LoginResponse, LoginResponses, LogLevel, LogoutData, LogoutErrors, LogoutResponses, LogRecord, LogSearchLine, LogSeverity, LogSource, LogsQuery, LogsResponse, LogStream, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsErrors, LookupDnsARecordsResponse, LookupDnsARecordsResponses, ManagedDomainResponse, ManualAction, ManualActionTiming, McpDefinitionResponse, MessageContent, MessagePart, MessageResponse, MeteredMode, MetricAggregation, MetricBucket, MetricDataPoint, MetricsOverTimeResponse, MetricsQuery, MetricsRangeQuery, MetricsStatusResponse, MetricsStoreKind, MetricsSummaryResponse, MetricType, MfaRequiredResponse, MfaSetupResponse, MfaVerificationRequest, MigrationStep, MigrationSummary, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenRequest, MintEnrollmentTokenResponse, MintEnrollmentTokenResponse2, MintEnrollmentTokenResponses, MiscResult, MkdirBody, MkdirData, MkdirErrors, MkdirResponse, MkdirResponses, ModelInfo, ModelListResponse, ModelPricing, ModelUsage, MonitoringSettings, MonitoringSettingsMasked, MonitorResponse, MonitorStatus, MrrBucketResponse, MultiNodeSettings, MultiNodeSettingsMasked, MxResult, NavEntry, NavSection, NetworkConfiguration, NetworkMode, NixpacksPresetConfig, NixpacksProvider, NodeContainerListResponse, NodeContainerResponse, NodeCostInfo, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponse, NodeHeartbeatResponses, NodeInfoResponse, NodeListResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponse, NodeMetricsGetRangeResponses, NotificationPreferencesResponse, NotificationProviderResponse, ObservabilityCompressionSettings, ObservabilityEvent, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventErrors, ObservabilityFullEventResponse, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsErrors, ObservabilityListEventsResponse, ObservabilityListEventsResponses, ObservabilityRetentionSettings, OidcCallbackData, OidcProviderResponse, OidcProvidersListResponse, OidcProviderSummary, OidcProviderUserResponse, OidcRoleMappingResponse, OidcTestConnectionResponse, OnDemandCertAttemptResponse, OnDemandCertRow, OnDemandTlsSettings, OpenAiError, OpenAiErrorResponse, OperatingSystemCount, OperationResultResponse, OperationResultsResponse, OtelDashboardResponse, OtelDashboardsResponse, OtelMetricAlertRuleResponse, OtelMetricAlertsResponse, OtelMetricLabelKeysResponse, OtelMetricLabelValuesResponse, OtelMetricNamesResponse, OtelMetricsResponse, OutlierAlgorithm, OutlierParams, OverprovisioningAssessment, OverprovisioningVerdict, PageActivityBucket, PageCountryStats, PageFlowEntry, PageFlowQuery, PageFlowResponse, PageHourlySessionsQuery, PageHourlySessionsResponse, PagePathDetailQuery, PagePathDetailResponse, PagePathInfo, PagePathSparkline, PagePathSparklinePoint, PagePathsQuery, PagePathsResponse, PagePathsSparklineQuery, PagePathsSparklineResponse, PagePathVisitorsQuery, PagePathVisitorsResponse, PageReferrerStats, PagesComparisonResponse, PageSessionComparison, PageSessionStats, PageSessionStatsQuery, PageTransition, PageVisit, PageVisitorSession, PaginatedEmailsResponse, PaginatedEntitiesResponse, PaginatedErrorEventsResponse, PaginatedErrorGroupsResponse, PaginatedEventsResponse, PaginatedExternalImagesResponse, PaginatedProjectList, PaginatedStaticBundlesResponse, Pagination, PaginationMeta, PaginationParams, PasswordProtectionConfig, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponse, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PatchPreviewGatewaySettingsResponses, PatchSettingsRequest, PathVisitors, PathVisitorsAnalyticsQuery, PathVisitorsResponse, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponse, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponse, PauseSandboxResponses, PeerEntry, PeerListResponse, PendingActionResponse, PerformanceMetricsQuery, PerformanceMetricsResponse, PermissionInfo, PgUpgradeLogResponse, PgUpgradeResponse, PipelineStats, PipelineStatsResponse, PlanComplexity, PlanMetadata, PlanRestoreData, PlanRestoreError, PlanRestoreErrors, PlanRestoreResponse, PlanRestoreResponses, PlanSourceBackup, PlanTarget, PlatformInfo, PluginManifest, PortMapping, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponse, PostDnsAckResponses, PostgresWalHealth, PresetConfigSchema, PresetInfo, PresetResponse, PreviewAlertData, PreviewAlertError, PreviewAlertErrors, PreviewAlertResponse, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponse, PreviewFunnelMetricsResponses, PreviewGatewaySettings, PreviewGatewaySettingsMasked, PreviewGatewaySettingsResponse, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponse, PreviewHostnameModeResponses, PricingResponse, ProblemDetails, ProjectConfiguration, ProjectDashboardAnalytics, ProjectDsnResponse, ProjectHealthSummary, ProjectInfo, ProjectMonitorHealth, ProjectPresetResponse, ProjectQuery, ProjectRef, ProjectResponse, ProjectSecretEnvironmentInfo, ProjectSecretResponse, ProjectServiceInfo, ProjectsHealthResponse, ProjectsMonitorHealthResponse, ProjectStatisticsResponse, ProjectStatsBreakdown, ProjectType, ProjectUsageInfoResponse, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentRequest, PromoteDeploymentResponse, PromoteDeploymentResponses, PropertyBreakdownItem, PropertyBreakdownQuery, PropertyBreakdownResponse, PropertyColumn, PropertyTimelineItem, PropertyTimelineQuery, PropertyTimelineResponse, Protocol, ProviderCatalogDto, ProviderCatalogResponse, ProviderConfig, ProviderConfigMasked, ProviderDeletionCheckResponse, ProviderDescriptor, ProviderKeyResponse, ProviderMetadata, ProviderResponse, ProviderUsage, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponse, ProvisionDomainResponses, ProvisionResponse, ProxyLogResponse, ProxyLogsPaginatedResponse, ProxyRequest, PublicHostnameStrategy, PublicPresetResponse, PublicRepositoryInfo, PurgeLogsRequest, PurgeProjectLogsData, PurgeProjectLogsError, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushedExternalImageResponse, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponse, PushExternalImageResponses, PushImageRequest, QueryDataData, QueryDataErrors, QueryDataRequest, QueryDataResponse, QueryDataResponse2, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesErrors, QueryGenaiTracesResponse, QueryGenaiTracesResponses, QueryLogsData, QueryLogsError, QueryLogsErrors, QueryLogsResponse, QueryLogsResponses, QueryMetricsData, QueryMetricsError, QueryMetricsErrors, QueryMetricsResponse, QueryMetricsResponses, QueryTracesData, QueryTracesError, QueryTracesErrors, QueryTracesResponse, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesErrors, QueryTraceSummariesResponse, QueryTraceSummariesResponses, QuotaResponse, RateLimitConfig, RateLimitSettings, ReachabilityStatus, ReadFileData, ReadFileErrors, ReadFileResponse, ReadFileResponse2, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RebuildSandboxImageData, RebuildSandboxImageErrors, RebuildSandboxImageResponses, RecentActivityQuery, RecentActivityResponse, RecentEventResponse, RecentQueryParams, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponse, RecordEventMetricsResponses, RecordListResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsErrors, RecordSpeedMetricsResponse, RecordSpeedMetricsResponses, RecoveryTarget, ReferrerCount, ReferrersAnalyticsQuery, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponse, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnRequest, RegenerateDsnResponse, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponse, RegisterExternalImageResponses, RegisterImageRequest, RegisterNodeApiRequest, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponse, RegisterNodeResponse2, RegisterNodeResponses, RegisterRequest, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponse, ReinstallGitlabWebhookResponses, ReinstallWebhookResponse, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponse, RejectPendingActionResponses, ReleaseListResponse, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponse, ReloadPluginsResponses, ReloadResponse, RemoteDeploymentResponse, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponse, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponse, RemoveManagedDomainResponses, RemoveNodeResponse, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponse, RemoveRoleResponses, RenameConversationData, RenameConversationErrors, RenameConversationRequest, RenameConversationResponse, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponse, RenewDomainResponses, RepositoryListQuery, RepositoryListResponse, RepositoryPresetResponse, RepositoryResponse, RepositorySyncStartedResponse, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponse, RequestPasswordResetResponses, RequestRow, ResetPasswordData, ResetPasswordErrors, ResetPasswordRequest, ResetPasswordResponse, ResetPasswordResponses, ResizeSandboxBody, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponse, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, ResolvedEnvVarResponse, ResolvedEnvVarSource, ResourceCounts, ResourceFootprint, ResourceInfo, ResourceLimitApplyResult, ResourceLimits, ResourceLimitsResponse, ResourceLimitsUpdateResponse, ResourcesBody, RestartContainerData, RestartContainerErrors, RestartContainerResponse, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponse, RestartSandboxResponses, RestoreCapabilities, RestoreCapabilitiesResponse, RestorePlan, RestoreRequestMode, RestoreRunView, RestoreUserData, RestoreUserErrors, RestoreUserResponse, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponse, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponse, ResumeSandboxResponses, RetentionCleanupFailure, RetentionCleanupReport, RetryClusterData, RetryClusterErrors, RetryClusterRequest, RetryClusterResponse, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponse, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponse, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponse, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponse, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponse, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponse, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponse, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponse, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponse, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponse, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponse, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueRotateTokenResponses, RevenueRow, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponse, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponse, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponse, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponse, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponse, RevokeJoinTokenResponses, RiskLevel, RoleInfo, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponse, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponse, RollbackToDeploymentResponses, RootfsCacheEntry, RootfsGcData, RootfsGcReport, RootfsGcResponses, RootfsReport, RootfsReportData, RootfsReportResponses, RootfsVmEntry, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponse, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponse, RotateDeploymentTokenResponses, RouteRefreshResponse, RouteResponse, RouteRole, RouteUser, RouteUserWithRoles, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceErrors, RunBackupForSourceResponse, RunBackupForSourceResponses, RunBackupRequest, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponse, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupErrors, RunExternalServiceBackupRequest, RunExternalServiceBackupResponse, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowError, RunScheduleNowErrors, RunScheduleNowResponse, RunScheduleNowResponses, S3ConnectionTestResponse, S3CredentialsResponse, S3SourceResponse, S3SourceResponseWritable, SandboxDomainResponse, SandboxEvent, SandboxEventsResponse, SandboxInner, SandboxResponse, SandboxRoute, SandboxStatusResponse, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenRequest, SaveAgentTokenResponse, SaveAgentTokenResponse2, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponse, SaveAiProviderCredentialResponses, SaveCredentialRequest, SaveCredentialResponse, ScalewayCredentialsRequest, ScanResponse, ScheduleRunEntry, ScheduleRunJobEntry, ScheduleRunListResponse, ScheduleRunResponse, ScheduleRunSummary, ScheduleRunSummaryList, ScreenshotSettings, SearchLogsData, SearchLogsError, SearchLogsErrors, SearchLogsRequest, SearchLogsResponse, SearchLogsResponse2, SearchLogsResponses, SearchMode, Seasonality, SecretResponse, SecurityConfig, SecurityHeadersConfig, SecurityHeadersSettings, SendEmailData, SendEmailErrors, SendEmailRequestBody, SendEmailResponse, SendEmailResponseBody, SendEmailResponses, SendMessageData, SendMessageErrors, SendMessageRequest, SendMessageResponses, SensitiveConfigValueResponse, SensitiveMcpConfigValueResponse, SensitiveValueResponse, SentryChunkUploadResponse, SentryCreateReleaseRequest, SentryEventRequest, SentryEventResponse, SentryReleaseFileResponse, SentryReleaseProjectRef, SentryReleaseResponse, SeriesStateEntry, ServiceAccessInfo, ServiceAction, ServiceAlertRuleResponse, ServiceBackupEntryResponse, ServiceBackupListResponse, ServiceCreateAlertRuleRequest, ServiceHealthResponse, ServiceHealthStatusBatchResponse, ServiceHealthStatusEntryResponse, ServiceMemberInfo, ServiceParameter, ServicePlan, ServiceResourceLimits, ServiceRuntimeReport, ServiceStatsReport, ServiceTypeInfo, ServiceTypeRoute, ServiceUpdateAlertRuleRequest, SesCredentialsRequest, SessionDetails, SessionDetailsQuery, SessionEvent, SessionEventDto, SessionEventsQuery, SessionEventsResponse, SessionLogsQuery, SessionLogsResponse, SessionReplayEventsRequest, SessionReplayInfoDto, SessionReplayInitRequest, SessionReplayInitResponse, SessionReplayWithEventsDto, SessionReplayWithVisitorDto, SessionRequestLog, SessionSummary, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceErrors, SetDefaultS3SourceResponse, SetDefaultS3SourceResponses, SetPreviewPasswordBody, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponse, SetPreviewPasswordResponse2, SetPreviewPasswordResponses, SetRequest, SetResponse, SettingsUpdateResponse, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeRequest, SetupDnsChallengeResponse, SetupDnsChallengeResponse2, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsRequest, SetupDnsResponse, SetupDnsResponse2, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponse, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponse, SetupMfaResponses, SiblingRef, SkillDefinitionResponse, SlackConfig, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponse, SleepEnvironmentResponses, SlowQueriesResponse, SlowQueryRow, SmartFilter, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponse, SmokeTestAgentResponses, SmokeTestResponse, SmtpCredentialsRequest, SmtpEncryptionRoute, SmtpResult, SourceBackupEntry, SourceBackupIndexResponse, SourceBody, SourceFileListResponse, SourceFileResponse, SourceMapListResponse, SourceMapResponse, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponse, SourceSandboxResponses, SourceType, SpanEvent, SpanKind, SpanRecord, SpanRow, SpanStatusCode, SpeedMetricsPayload, SpeedSegmentFilters, StaleSlot, StartAnalysisData, StartAnalysisErrors, StartAnalysisRequest, StartAnalysisResponse, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponse, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeRequest, StartPgUpgradeResponse, StartPgUpgradeResponses, StartRestoreData, StartRestoreError, StartRestoreErrors, StartRestoreRequest, StartRestoreResponse, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponse, StartServiceResponses, StaticBundleResponse, StaticParams, StaticPresetConfig, StatPathData, StatPathErrors, StatPathResponse, StatPathResponses, StatResponse, StatsFilters, StatusBucket, StatusBucketedResponse, StatusCodeCount, StatusCodesQuery, StatusPageOverview, StepConversionResponse, StepResourceType, StepResult, StopContainerData, StopContainerErrors, StopContainerResponse, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponse, StopSandboxResponses, StopSequence, StopServiceData, StopServiceErrors, StopServiceResponse, StopServiceResponses, StorageQuota, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, StripeConfig, SyncedRepositoryListQuery, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponse, SyncRepositoriesResponses, SyntaxResult, TagInfo, TagListResponse, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsError, TailLogsErrors, TailLogsRequest, TailLogsResponses, TargetRecommendation, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponse, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponse, TeardownEnvironmentResponses, TemplateResponse, TestEmailRequest, TestEmailResponse, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponse, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponse, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponse, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdErrors, TestProviderKeyByIdResponse, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineErrors, TestProviderKeyInlineResponse, TestProviderKeyInlineResponses, TestProviderKeyRequest, TestProviderKeyResponse, TestProviderResponse, TestProviderResponse2, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponse, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionErrors, TestS3SourceConnectionResponse, TestS3SourceConnectionResponses, TimeBucketStats, TimeBucketStatsResponse, TimeseriesBucket, TimeseriesQueryParams, TlsMode, TodayStatsResponse, ToggleDeploymentMetricsRequest, ToggleServiceMetricsRequest, TokenRenewalRequest, ToolCallEvent, ToolInfo, ToolResultEvent, TopModelsQueryParams, TraceProjectRef, TracesResponse, TraceSummariesResponse, TraceSummary, TrackClickData, TrackClickErrors, TrackedLinkResponse, TrackingEventResponse, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentRequest, TriggerAgentResponse, TriggerAgentResponses, TriggerDigestResponse, TriggerPipelinePayload, TriggerPipelineResponse, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponse, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanError, TriggerScanErrors, TriggerScanRequest, TriggerScanResponse, TriggerScanResponse2, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponse, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponse, TriggerWeeklyDigestResponses, TtlRequest, TtlResponse, TxtRecord, UiManifest, UiRoute, UndrainNodeResponse, UnifiedTrace, UniqueCountsQuery, UniqueCountsResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponse, UnlinkServiceFromProjectResponses, UnsupportedFeature, UpdateAdminGateRequest, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderRequest, UpdateAiProviderResponse, UpdateAiProviderResponse2, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertError, UpdateAlertErrors, UpdateAlertResponse, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleRequest, UpdateAlertRuleResponse, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyRequest, UpdateApiKeyResponse, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployRequest, UpdateAutomaticDeployResponse, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleErrors, UpdateBackupScheduleRequest, UpdateBackupScheduleResponse, UpdateBackupScheduleResponses, UpdateBlobRequest, UpdateBlobResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderRequest, UpdateCloudflareProviderResponse, UpdateCloudflareProviderResponses, UpdateConfigBody, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponse, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainRequest, UpdateCustomDomainResponse, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardError, UpdateDashboardErrors, UpdateDashboardRequest, UpdateDashboardResponse, UpdateDashboardResponses, UpdateDeploymentConfigRequest, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenRequest, UpdateDeploymentTokenResponse, UpdateDeploymentTokenResponses, UpdateDnsProviderRequest, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderRequest, UpdateEmailProviderResponse, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsRequest, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainRequest, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableRequest, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupRequest, UpdateErrorGroupResponses, UpdateExternalServiceRequest, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponse, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsRequest, UpdateGitSettingsResponse, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponse, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponse, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusRequest, UpdateIncidentStatusResponse, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlErrors, UpdateIpAccessControlRequest, UpdateIpAccessControlResponse, UpdateIpAccessControlResponses, UpdateKvRequest, UpdateKvResponse, UpdateManagedDomainApiRequest, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponse, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpRequest, UpdateMcpResponse, UpdateMcpResponses, UpdateMetricAlertRequest, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderRequest, UpdateNotificationEmailProviderResponse, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponse, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderRequest, UpdateOidcProviderResponse, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesRequest, UpdatePreferencesResponse, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponse, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretRequest, UpdateProjectSecretResponse, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsRequest, UpdateProjectSettingsResponse, UpdateProjectSettingsResponses, UpdateProviderCredentialsRequest, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyErrors, UpdateProviderKeyRequest, UpdateProviderKeyResponse, UpdateProviderKeyResponses, UpdateProviderRequest, UpdateProviderResponse, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteRequest, UpdateRouteResponse, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceErrors, UpdateS3SourceRequest, UpdateS3SourceResponse, UpdateS3SourceResponses, UpdateSecretBody, UpdateSelfData, UpdateSelfErrors, UpdateSelfRequest, UpdateSelfResponse, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponse, UpdateServiceResourcesResponses, UpdateServiceResponse, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationErrors, UpdateSessionDurationRequest, UpdateSessionDurationResponse, UpdateSessionDurationResponse2, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponse, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillRequest, UpdateSkillResponse, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderRequest, UpdateSlackProviderResponse, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsErrors, UpdateSpeedMetricsPayload, UpdateSpeedMetricsResponse, UpdateSpeedMetricsResponses, UpdateStatusResponse, UpdateTokenRequest, UpdateTokenResponse, UpdateUserData, UpdateUserErrors, UpdateUserRequest, UpdateUserResponse, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderRequest, UpdateWebhookProviderResponse, UpdateWebhookProviderResponses, UpdateWebhookRequestBody, UpdateWebhookResponse, UpdateWebhookResponses, UpgradeExternalServiceRequest, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradePreviewGatewayResponses, UpgradeRequest, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponse, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponse, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponse, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponse, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponse, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponse, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponse, UploadStaticBundleResponses, UpsertAgentRequest, UpsertSecretData, UpsertSecretErrors, UpsertSecretRequest, UpsertSecretResponse, UpsertSecretResponses, UptimeDataPoint, UptimeHistoryResponse, UsageFilter, UsageInfo, UsageLogEntry, UsageLogPage, UsageQueryParams, UsageSource, UsageSummary, UserResponse, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponse, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailRequest, ValidateEmailResponse, ValidateEmailResponse2, ValidateEmailResponses, ValidationLevel, ValidationReport, ValidationResponse, ValidationResult, ValidationStatus, ValidationSummary, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponse, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponse, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponse, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponse, VerifyMfaChallengeResponses, VerifyMfaRequest, ViewItem, ViewsOverTime, ViewsOverTimeQuery, VisitorDetails, VisitorFacets, VisitorFacetsQuery, VisitorFacetValue, VisitorInfo, VisitorJourneyQuery, VisitorJourneyResponse, VisitorLocationsQuery, VisitorRecord, VisitorSegmentFilters, VisitorSessionsQuery, VisitorSessionsResponse, VisitorsListQuery, VisitorsResponse, VisitorStats, VisitorWithGeolocation, VolumeMount, VolumeType, VulnerabilityResponse, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponse, WakeEnvironmentResponses, WalWarning, WalWarningSeverity, WebhookConfig, WebhookDeliveryResponse, WebhookResponse, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerRequest, WebhookTriggerResponse, WebhookTriggerResponse2, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunRequest, WorkflowDryRunResponse, WorkflowDryRunResponses, WorkloadDescriptor, WorkloadId, WorkloadStatus, WorkloadType, WriteFileBody, WriteFileData, WriteFileErrors, WriteFileResponse, WriteFileResponses, WriteFilesBody, WriteFilesData, WriteFilesErrors, WriteFilesResponse, WriteFilesResponse2, WriteFilesResponses, ZoneListResponse } from './types.gen'; +export { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobHead, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, rebuildSandboxImage, recordConsoleEvent, recordEventMetrics, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, sendMessage, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, streamEvents, streamRunEvents, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from './sdk.gen'; +export type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, AcmeOrderResponse, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponse, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponse, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponse, ActivateProviderResponses, ActiveVisitor, ActiveVisitorsQuery, ActiveVisitorsResponse, ActivityDay, ActivityEvent, ActivityGraphQuery, ActivityGraphResponse, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberRequest, AddClusterMemberResponse, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextRequest, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainRequest, AddEnvironmentDomainResponse, AddEnvironmentDomainResponses, AddEventsData, AddEventsError, AddEventsErrors, AddEventsRequest, AddEventsResponse, AddEventsResponse2, AddEventsResponses, AddManagedDomainApiRequest, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponse, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsErrors, AddSessionReplayEventsResponse, AddSessionReplayEventsResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponse, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponse, AdminDrainStatusResponses, AdminGateResponse, AdminGateSource, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponse, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponse, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponse, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponse, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponse, AdminUndrainNodeResponses, AgentConfigResponse, AgentRunLogResponse, AgentRunResponse, AgentRunWithLogsResponse, AgentSandboxSettings, AgentSandboxSettingsMasked, AggregatedBucketItem, AggregatedBucketsQuery, AggregatedBucketsResponse, AggregationLevel, AggregationTemporality, AiAgentBreakdownResponse, AiAgentBreakdownRow, AiAgentDescriptor, AiAgentPageRow, AiAgentPagesResponse, AiAgentTimelineResponse, AiAgentTimelineRow, AiConfigSettings, AiPageBreakdownResponse, AiPageBreakdownRow, AiStatusBreakdownResponse, AiStatusBreakdownRow, AlarmListResponse, AlarmResponse, AlarmSummaryResponse, AlertRuleResponse, AllocEntry, AnalyticsSessionEventsResponse, AnnotatedSpan, AnomalyAlgorithm, AnomalyParams, AnomalyPreviewPointResponse, AnomalyPreviewRequest, AnomalyPreviewResponse, ApiKeyListResponse, ApiKeyResponse, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeRequest, ApplyHostnameModeResponse, ApplyHostnameModeResponses, AppSettings, AppSettingsResponse, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponse, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponse, ArchiveFlagResponse2, ArchiveFlagResponses, ArchiveMode, AssignRoleData, AssignRoleErrors, AssignRoleRequest, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesErrors, AttachScheduleServicesRequest, AttachScheduleServicesResponse, AttachScheduleServicesResponse2, AttachScheduleServicesResponses, AuditLogIpInfo, AuditLogResponse, AuditLogUserInfo, AuthFlavorDto, AuthResponse, AuthStatusResponse, AuthTokenResponse, AutofixerRunResponse, AutofixerRunWithLogsResponse, AutofixRunConfig, AutoWatchParams, AvailableContainerInfo, AvailablePermissions, BackupAlertListResponse, BackupAlertResponse, BackupResponse, BackupScheduleResponse, BitbucketAuthInput, BlobCopyData, BlobCopyError, BlobCopyErrors, BlobCopyResponse, BlobCopyResponses, BlobDeleteData, BlobDeleteError, BlobDeleteErrors, BlobDeleteResponse, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponse, BlobDisableResponses, BlobDownloadData, BlobDownloadError, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponse, BlobEnableResponses, BlobHeadData, BlobHeadError, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListError, BlobListErrors, BlobListResponse, BlobListResponses, BlobPutData, BlobPutError, BlobPutErrors, BlobPutResponse, BlobPutResponses, BlobResponse, BlobStatusData, BlobStatusErrors, BlobStatusResponse, BlobStatusResponse2, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponse, BlobUpdateResponses, BranchInfo, BranchListResponse, BrowserCount, BrowsersQuery, BuildConfiguration, BuildLimitsSettings, CancelBackupData, CancelBackupError, CancelBackupErrors, CancelBackupResponse, CancelBackupResponse2, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponse, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponse, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponse, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponse, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunErrors, CancelScheduleRunResponse, CancelScheduleRunResponses, CertStatusResponse, ChallengeConfig, ChallengeError, ChallengeValidationStatus, ChangePasswordRequest, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponse, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceRequest, ChangeProjectSourceResponse, ChangeProjectSourceResponses, ChatCompletionChoice, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsErrors, ChatCompletionsResponse, ChatCompletionsResponses, ChatMessage, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponse, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponse, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponse, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponse, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedError, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponse, CheckProviderDeletionSafetyResponses, ChildBackupEntryResponse, ChildBackupListResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsErrors, CleanupExpiredBackupsRequest, CleanupExpiredBackupsResponse, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponse, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveRequest, CliDeviceApproveResponse, CliDeviceApproveResponse2, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponse, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponse, CliDeviceLookupResponse2, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollRequest, CliDevicePollResponse, CliDevicePollResponse2, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartRequest, CliDeviceStartResponse, CliDeviceStartResponse2, CliDeviceStartResponses, ClientOptions, CliLoginRequest, CliLogoutData, CliLogoutErrors, CliLogoutResponse, CliLogoutResponses, CloudflareConfig, CloudProvider, ClusterCapacity, ClusterDnsSettings, ClusterHealthReportResponse, ClusterMemberHealthResponse, ClusterMemberRequest, CmdBody, CmdData, CmdErrors, CmdInner, CmdKillBody, CmdKillData, CmdKillErrors, CmdKillResponse, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponse, CmdResponse2, CmdResponses, CommitExistsResponse, CommitInfo, CommitListResponse, Comparator, ComposePublicPort, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponse, ConfirmPendingActionResponses, ConnectionListQuery, ConnectionListResponse, ConnectionResponse, ConnectionTestResult, ConsoleEventPayload, ContainerActionResponse, ContainerDetailResponse, ContainerEnvironmentVariableValueResponse, ContainerInfoResponse, ContainerInventoryItem, ContainerListResponse, ContainerLogSettings, ContainerLogsQuery, ContainerMetricHistoryPoint, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponse, ContainerMetricsGetHistoryResponses, ContainerMetricsHistoryQuery, ContainerMetricsResponse, ContainerResponse, ContainerRuntimeInfo, ContainerStatsSample, ContentPart, ContextLine, ContextLogsRequest, ContextLogsResponse, ConversationDetailResponse, ConversationResponse, ConversationsQueryParams, ConversationSummary, CopyBlobRequest, CostAnalysis, CreateAgentData, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAlertData, CreateAlertError, CreateAlertErrors, CreateAlertResponse, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleRequest, CreateAlertRuleResponse, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyRequest, CreateApiKeyResponse, CreateApiKeyResponse2, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleErrors, CreateBackupScheduleRequest, CreateBackupScheduleResponse, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponse, CreateBitbucketProviderResponses, CreateBitbucketRequest, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderRequest, CreateCloudflareProviderResponse, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationRequest, CreateConversationResponse, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponse, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardError, CreateDashboardErrors, CreateDashboardRequest, CreateDashboardResponse, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenRequest, CreateDeploymentTokenResponse, CreateDeploymentTokenResponse2, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderRequest, CreateDnsProviderResponse, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainRequest, CreateDomainResponse, CreateDomainResponses, CreatedResource, CreateDsnData, CreateDsnErrors, CreateDsnRequest, CreateDsnResponse, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainRequest, CreateEmailDomainResponse, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderRequest, CreateEmailProviderResponse, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentRequest, CreateEnvironmentResponse, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableRequest, CreateEnvironmentVariableResponse, CreateEnvironmentVariableResponses, CreateExternalServiceRequest, CreateFlagData, CreateFlagErrors, CreateFlagRequest, CreateFlagResponse, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelRequest, CreateFunnelResponse, CreateFunnelResponse2, CreateFunnelResponses, CreateFunnelStep, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponse, CreateGenericProviderResponses, CreateGenericRequest, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponse, CreateGiteaPatProviderResponses, CreateGiteaPatRequest, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponse, CreateGithubPatProviderResponses, CreateGitHubPatRequest, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponse, CreateGitlabOauthProviderResponses, CreateGitLabOAuthRequest, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponse, CreateGitlabPatProviderResponses, CreateGitLabPatRequest, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponse, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponse, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponse, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentRequest, CreateIncidentResponse, CreateIncidentResponses, CreateIntegrationBody, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlErrors, CreateIpAccessControlRequest, CreateIpAccessControlResponse, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpRequest, CreateMcpResponse, CreateMcpResponses, CreateMetricAlertRequest, CreateMonitorData, CreateMonitorErrors, CreateMonitorRequest, CreateMonitorResponse, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderRequest, CreateNotificationEmailProviderResponse, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponse, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderRequest, CreateOidcProviderResponse, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingRequest, CreateOidcRoleMappingResponse, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponse, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanRequest, CreatePlanResponse, CreatePlanResponse2, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateRequest, CreateProjectFromTemplateResponse, CreateProjectFromTemplateResponse2, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponse, CreateProjectReleaseResponses, CreateProjectRequest, CreateProjectResponse, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretRequest, CreateProjectSecretResponse, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyErrors, CreateProviderKeyRequest, CreateProviderKeyResponse, CreateProviderKeyResponses, CreateProviderRequest, CreatePrResponse, CreatePrResponse2, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponse, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteRequest, CreateRouteResponse, CreateRouteResponses, CreateS3SourceData, CreateS3SourceError, CreateS3SourceErrors, CreateS3SourceRequest, CreateS3SourceResponse, CreateS3SourceResponses, CreateSandboxBody, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponse, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponse, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillRequest, CreateSkillResponse, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderRequest, CreateSlackProviderResponse, CreateSlackProviderResponses, CreateUserData, CreateUserErrors, CreateUserRequest, CreateUserResponse, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderRequest, CreateWebhookProviderResponse, CreateWebhookProviderResponses, CreateWebhookRequestBody, CreateWebhookResponse, CreateWebhookResponses, CronExecutionInfo, CronInfo, CrossProjectSiblingRef, CrossProjectTraceResponse, CurrentStatusResponse, CustomDomainRequest, CustomDomainResponse, CustomerMovementResponse, DashboardLayout, DashboardProjectsAnalyticsQuery, DashboardProjectsAnalyticsResponse, DashboardSection, DashboardTile, DatabaseMetricsResponse, DatabaseMetricsRow, DataImplication, DataImplicationSeverity, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponse, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAlertData, DeleteAlertError, DeleteAlertErrors, DeleteAlertResponse, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponse, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponse, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupError, DeleteBackupErrors, DeleteBackupResponse, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleErrors, DeleteBackupScheduleResponse, DeleteBackupScheduleResponses, DeleteBlobRequest, DeleteBlobResponse, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponse, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponse, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardError, DeleteDashboardErrors, DeleteDashboardResponse, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponse, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponse, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponse, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponse, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponse, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponse, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponse, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponse, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponse, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponse, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponse, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlErrors, DeleteIpAccessControlResponse, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponse, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponse, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponse, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponse, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponse, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyErrors, DeleteProviderKeyResponse, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponse, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponse, DeleteReleaseSourceMapsResponses, DeleteResponse, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponse, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceErrors, DeleteS3SourceResponse, DeleteS3SourceResponses, DeleteScanData, DeleteScanError, DeleteScanErrors, DeleteScanResponse, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponse, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponse, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponse, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponse, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponse, DeleteStaticBundleResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponse, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponse, DeleteWebhookResponses, DelRequest, DelResponse, DeployFromImageData, DeployFromImageErrors, DeployFromImageRequest, DeployFromImageResponse, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadQuery, DeployFromImageUploadResponse, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticRequest, DeployFromStaticResponse, DeployFromStaticResponses, DeploymentConfig, DeploymentConfigSnapshot, DeploymentConfiguration, DeploymentContainerLogContentResponse, DeploymentContainerLogResponse, DeploymentContainerLogsListResponse, DeploymentEnvironmentResponse, DeploymentJobResponse, DeploymentJobsResponse, DeploymentListResponse, DeploymentMetadata, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponse, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DeploymentResponse, DeploymentStateResponse, DeploymentStrategy, DeploymentTokenListResponse, DeploymentTokenResponse, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponse, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceErrors, DetachScheduleServiceResponse, DetachScheduleServiceResponses, DetectionConfig, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponse, DetectPublicPresetsResponses, DeviceCount, DigestSections, Direction, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponse, DisableBackupScheduleResponses, DisableBlobResponse, DisableKvResponse, DisableMfaData, DisableMfaErrors, DisableMfaRequest, DisableMfaResponse, DisableMfaResponses, DiscoverRequest, DiscoverResponse, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponse, DiscoverWorkloadsResponses, DiskInfo, DiskSpaceAlert, DiskSpaceAlertSettings, DiskSpaceCheckResult, DnsAckRequest, DnsAckResponse, DnsChallengeRecordResult, DnsChangesResponse, DnsCompletionResponse, DnsLookupError, DnsLookupRequest, DnsLookupResponse, DnsProviderCredentials, DnsProviderResponse, DnsProviderSettings, DnsProviderSettingsMasked, DnsProviderType, DnsRecord, DnsRecordChange, DnsRecordContent, DnsRecordResponse, DnsRecordSetupResult, DnsRecordStatusResponse, DnsZone, DockerComposePresetConfig, DockerfilePresetConfig, DockerfileVariant, DockerRegistrySettings, DockerRegistrySettingsMasked, DomainAction, DomainChallengeResponse, DomainData, DomainEnvironmentResponse, DomainError, DomainErrors, DomainPlan, DomainResponse, DomainResponse2, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponse, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponse, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponse, DownloadSkillArchiveResponses, DrainNodeResponse, DrainStatusResponse, DropOffPoint, EmailConfig, EmailDomainResponse, EmailDomainWithDnsResponse, EmailProviderResponse, EmailProviderTypeRoute, EmailRequest, EmailResponse, EmailStatsResponse, EmailStatusData, EmailStatusErrors, EmailStatusResponse, EmailStatusResponse2, EmailStatusResponses, EmailTrackingResponse, EmailTrackingSetupResponse, EmailTrackingStatusResponse, EmbeddingData, EmbeddingInput, EmbeddingRequest, EmbeddingResponse, EmbeddingsData, EmbeddingsError, EmbeddingsErrors, EmbeddingsResponse, EmbeddingsResponses, EmbeddingUsage, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponse, EnableBackupScheduleResponses, EnableBlobRequest, EnableBlobResponse, EnableKvRequest, EnableKvResponse, EnablePgStatStatementsResponse, EndpointDto, EnqueuedJob, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorRequest, EnrichVisitorResponse, EnrichVisitorResponse2, EnrichVisitorResponses, EnrollmentTokenInfo, EnrollmentTokenListResponse, EntityInfoResponse, EntityResponse, EnvironmentConfiguration, EnvironmentDomainResponse, EnvironmentInfo, EnvironmentResponse, EnvironmentVariable, EnvironmentVariableInfo, EnvironmentVariableResponse, EnvironmentVariableValueResponse, EnvVarInput, EnvVarIntegrationInfo, EnvVarResponse, EnvVarTemplateResponse, ErrorDashboardStatsQuery, ErrorDashboardStatsResponse, ErrorEventResponse, ErrorGroupResponse, ErrorGroupStatsResponse, ErrorResponse, ErrorRow, ErrorTimeSeriesDataResponse, ErrorTimeSeriesQuery, EventActivityBucket, EventBreakdown, EventBrowserStats, EventCount, EventCountryStats, EventDetailQuery, EventDetailResponse, EventEntriesQuery, EventEntriesResponse, EventEntryInfo, EventKind, EventMetricsPayload, EventReferrerStats, EventsCountQuery, EventsResponse, EventTimeline, EventTimelineQuery, EventType, EventTypeBreakdown, EventTypeBreakdownQuery, EventTypeResponse, EventTypesResponse, EventVisitorInfo, EventVisitorsQuery, EventVisitorsResponse, ExecBody, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponse, ExecDetachedResponse2, ExecDetachedResponses, ExecErrors, ExecResponse, ExecResponse2, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponse, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportRequest, ExecuteImportResponse, ExecuteImportResponse2, ExecuteImportResponses, ExecuteOperationRequest, ExpireRequest, ExpireResponse, ExplorerSupportResponse, ExtendTimeoutBody, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponse, ExtendTimeoutResponses, ExternalImageResponse, ExternalServiceBackupResponse, ExternalServiceDetails, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceInfo, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceSummary, FieldResponse, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponse, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponse, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponse, FindConversationResponses, FiringSeriesEntry, FlagEnvironmentResponse, FlagListResponse, FlagResponse, FlagSnapshot, FlagSnapshotResponse, FlagValueType, ForecastAlgorithm, ForecastParams, FullError, FullEvent, FullRequest, FunnelMetricsResponse, FunnelResponse, GatewayStatus, GenAiEvent, GenAiSpanDetail, GenAiTraceDetailResponse, GenAiTraceSummariesResponse, GenAiTraceSummary, GeneralStatsQuery, GeneralStatsResponse, GenerateDockerfileRequest, GenerateDockerfileResponse, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponse, GenerateJoinTokenResponse2, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponse, GeneratePresetDockerfileResponses, GeoLocationResponse, GeoRestrictionsConfig, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponse, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponse, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponse, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponse, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponse, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponse, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesErrors, GetAiAgentPagesResponse, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineErrors, GetAiAgentTimelineResponse, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownErrors, GetAiPageBreakdownResponse, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponse, GetAiStatusBreakdownResponses, GetAlertData, GetAlertError, GetAlertErrors, GetAlertResponse, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponse, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponse, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponse, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponse, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponse, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponse, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponse, GetApiKeyPermissionsResponses, GetApiKeyResponse, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponse, GetAuditLogResponses, GetBackupData, GetBackupError, GetBackupErrors, GetBackupResponse, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponse, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponse, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponse, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponse, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponse, GetChallengeTokenResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponse, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponse, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponse, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponse, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponse, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponse, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponse, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailErrors, GetConversationDetailResponse, GetConversationDetailResponses, GetConversationErrors, GetConversationResponse, GetConversationResponses, GetConversationsData, GetConversationsError, GetConversationsErrors, GetConversationsResponse, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponse, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponse, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponse, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponse, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponse, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponse, GetCustomDomainResponses, GetDashboardData, GetDashboardError, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponse, GetDashboardProjectsAnalyticsResponses, GetDashboardResponse, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponse, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponse, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponse, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponse, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponse, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponse, GetDeploymentOperationStatusResponses, GetDeploymentResponse, GetDeploymentResponses, GetDeploymentsParams, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponse, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponse, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponse, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponse, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponse, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponse, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponse, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponse, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponse, GetDomainOrderResponses, GetDomainResponse, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponse, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponse, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponse, GetEmailProviderResponses, GetEmailResponse, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponse, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponse, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponse, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponse, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponse, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponse, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponse, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponse, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesQuery, GetEnvironmentVariablesResponse, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponse, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponse, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponse, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponse, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponse, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponse, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponse, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponse, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponse, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponse, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponse, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponse, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponse, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponse, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponse, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponse, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsQuery, GetFunnelMetricsResponse, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceErrors, GetGenaiTraceResponse, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponse, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponse, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponse, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponse, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponse, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponse, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponse, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponse, GetGroupedPageMetricsResponses, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponse, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponse, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponse, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponse, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponse, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlErrors, GetIpAccessControlResponse, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationErrors, GetIpGeolocationResponse, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponse, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponse, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanError, GetLatestScanErrors, GetLatestScanResponse, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponse, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponse, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextError, GetLogContextErrors, GetLogContextResponse, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponse, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeErrors, GetMetricsOverTimeResponse, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponse, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponse, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponse, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnRequest, GetOrCreateDsnResponse, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponse, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponse, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponse, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponse, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponse, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponse, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponse, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsErrors, GetPerformanceMetricsResponse, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponse, GetPgUpgradeLogsResponses, GetPgUpgradeResponse, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsErrors, GetPipelineStatsResponse, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponse, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponse, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponse, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingError, GetPricingErrors, GetPricingResponse, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponse, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponse, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponse, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponse, GetProjectResponses, GetProjectsData, GetProjectSecretsQuery, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponse, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysErrors, GetProjectSessionReplaysQuery, GetProjectSessionReplaysResponse, GetProjectSessionReplaysResponse2, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthErrors, GetProjectsHealthResponse, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponse, GetProjectsMonitorHealthResponses, GetProjectsResponse, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponse, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponse, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponse, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponse, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponse, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponse, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponse, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdErrors, GetProxyLogByIdResponse, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponse, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsError, GetProxyLogsErrors, GetProxyLogsResponse, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponse, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponse, GetPublicRepositoryResponses, GetQuotaData, GetQuotaError, GetQuotaErrors, GetQuotaResponse, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponse, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponse, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponse, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponse, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponse, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponse, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponse, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponse, GetRepositoryTagsResponses, GetRequest, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponse, GetResolvedEnvironmentVariableValueResponses, GetResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponse, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunError, GetRestoreRunErrors, GetRestoreRunResponse, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponse, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponse, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponse, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponse, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceError, GetS3SourceErrors, GetS3SourceResponse, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponse, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponse, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentErrors, GetScanByDeploymentResponse, GetScanByDeploymentResponses, GetScanData, GetScanError, GetScanErrors, GetScanResponse, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponse, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponse, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponse, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponse, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponse, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponse, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponse, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponse, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponse, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponse, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponse, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayError, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsErrors, GetSessionReplayEventsResponse, GetSessionReplayEventsResponses, GetSessionReplayResponse, GetSessionReplayResponse2, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponse, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponse, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponse, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponse, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponse, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponse, GetTagsByRepositoryIdResponses, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsErrors, GetTimeBucketStatsResponse, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsError, GetTodayStatsErrors, GetTodayStatsResponse, GetTodayStatsResponses, GetTraceData, GetTraceError, GetTraceErrors, GetTraceResponse, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceErrors, GetUnifiedTraceResponse, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponse, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsQuery, GetUniqueEventsResponse, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponse, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponse, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderErrors, GetUsageByProviderResponse, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentError, GetUsageRecentErrors, GetUsageRecentResponse, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryErrors, GetUsageSummaryResponse, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesErrors, GetUsageTimeseriesResponse, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsErrors, GetUsageTopModelsResponse, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponse, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponse, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponse, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponse, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponse, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponse, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsErrors, GetVisitorSessionsQuery, GetVisitorSessionsResponse, GetVisitorSessionsResponse2, GetVisitorSessionsResponses, GetVisitorsResponse, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponse, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponse, GetWebhookResponses, GitPushEvent, GitRefResponse, GitSourcePlan, GlobalConversationResponse, GlobalEventStatsResponse, GlobalMrrResponse, GlobalRecentEventResponse, GlobalRevenueSummaryResponse, GroupedPageMetric, GroupedPageMetricsQuery, GroupedPageMetricsResponse, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponse, HasAnalyticsEventsResponse2, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponse, HasErrorGroupsResponse2, HasErrorGroupsResponses, HasEventsQuery, HasEventsResponse, HasMetricsQuery, HasMetricsResponse, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsErrors, HasPerformanceMetricsResponse, HasPerformanceMetricsResponses, HealthCheckConfiguration, HealthCheckEntryResponse, HealthResponse, HealthStatus, HealthSummary, HeartbeatApiRequest, HeartbeatResponse, HierarchyLevel, HistogramSummary, HostnameChange, HostnamePreviewResponse, HourlyPageSessions, HourlyVisitsQuery, HttpChallengeDebugResponse, ImportCredentials, ImportExecutionStatus, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceRequest, ImportExternalServiceResponse, ImportExternalServiceResponses, ImportOutcomeResponse, ImportPlan, ImportRowErrorResponse, ImportSelector, ImportSource, ImportSourceCapabilities, ImportSourceInfo, ImportStatusResponse, IncidentBucket, IncidentBucketedResponse, IncidentResponse, IncidentUpdateResponse, IncrRequest, IncrResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsError, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsError, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponse, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathError, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesError, IngestTracesErrors, IngestTracesResponses, InitAuthResponse, InitSessionReplayData, InitSessionReplayError, InitSessionReplayErrors, InitSessionReplayResponse, InitSessionReplayResponses, Insight, InsightSeverity, InsightsResponse, InsightStatus, IntegrationResponse, IpAccessControlQuery, IpAccessControlResponse, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponse, JobStatusResponse2, JobStatusResponses, JobSummaryResponse, JoinTokenStatusResponse, JourneyEvent, JourneySession, KeysRequest, KeysResponse, KillJobBody, KillJobData, KillJobErrors, KillJobResponse, KillJobResponses, KnownAiAgentsResponse, KvDelData, KvDelErrors, KvDelResponse, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponse, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponse, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponse, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponse, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponse, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponse, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponse, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponse, KvStatusResponse2, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponse, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponse, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponse, LatestRunForSourceResponses, LemonSqueezyConfig, LetsEncryptSettings, LineContext, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponse, LinkCustomDomainToCertificateResponses, LinkServiceRequest, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponse, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponse, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponse, ListAgentsResponse2, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponse, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponse, ListAlertRulesResponses, ListAlertsData, ListAlertsError, ListAlertsErrors, ListAlertsResponse, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponse, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponse, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysQuery, ListApiKeysResponse, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsQuery, ListAuditLogsResponse, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponse, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsErrors, ListBackupAlertsResponse, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenErrors, ListBackupChildrenResponse, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesErrors, ListBackupSchedulesResponse, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponse, ListBackupsForScheduleResponses, ListBlobsQuery, ListBlobsResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponse, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponse, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponse, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponse, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponse, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponse, ListCustomDomainsForProjectResponses, ListCustomDomainsResponse, ListDashboardsData, ListDashboardsError, ListDashboardsErrors, ListDashboardsResponse, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponse, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensQuery, ListDeploymentTokensResponse, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponse, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponse, ListDomainsResponse2, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponse, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponse, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponse, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponse, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesQuery, ListEntitiesResponse, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsQuery, ListErrorEventsResponse, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsQuery, ListErrorGroupsResponse, ListErrorGroupsResponses, ListEventsData, ListEventsResponse, ListEventsResponses, ListEventTypesData, ListEventTypesResponse, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponse, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponse, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponse, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponse, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponse, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponse, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponse, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponse, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsError, ListInsightsErrors, ListInsightsResponse, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlErrors, ListIpAccessControlResponse, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponse, ListJobsResponse2, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsErrors, ListKnownAiAgentsResponse, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponse, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponse, ListMcpsResponse2, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysErrors, ListMetricLabelKeysResponse, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesErrors, ListMetricLabelValuesResponse, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesError, ListMetricNamesErrors, ListMetricNamesResponse, ListMetricNamesResponses, ListModelsData, ListModelsError, ListModelsErrors, ListModelsResponse, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponse, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponse, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponse, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponse, ListOnDemandCertsResponse2, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponse, ListOrdersResponse2, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponse, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponse, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponse, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponse, ListPresetsResponse2, ListPresetsResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponse, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansError, ListProjectScansErrors, ListProjectScansResponse, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponse, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponse, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponse, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponse, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysError, ListProviderKeysErrors, ListProviderKeysResponse, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponse, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponse, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponse, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponse, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponse, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponse, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponse, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponse, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponse, ListRoutesResponses, ListRunsResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesErrors, ListS3SourcesResponse, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponse, ListSandboxesResponse2, ListSandboxesResponses, ListScansQuery, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsErrors, ListScheduleRunJobsResponse, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsErrors, ListScheduleRunsResponse, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesErrors, ListScheduleServicesResponse, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponse, ListSecretsResponse2, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponse, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponse, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesErrors, ListServiceSchedulesResponse, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponse, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponse, ListSkillsResponse2, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsErrors, ListSourceBackupsResponse, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponse, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponse, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponse, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponse, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponse, ListSyncedRepositoriesResponses, ListTagsResponse, ListTemplatesQuery, ListTemplatesResponse, ListUsersData, ListUsersErrors, ListUsersResponse, ListUsersResponses, ListVulnerabilitiesQuery, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponse, ListWebhooksResponses, LiveVisitorInfo, LiveVisitorsListResponse, LocationCount, LocationGranularity, LocationInfo, LoginData, LoginErrors, LoginRequest, LoginResponse, LoginResponses, LogLevel, LogoutData, LogoutErrors, LogoutResponses, LogRecord, LogSearchLine, LogSeverity, LogSource, LogsQuery, LogsResponse, LogStream, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsErrors, LookupDnsARecordsResponse, LookupDnsARecordsResponses, ManagedDomainResponse, ManualAction, ManualActionTiming, McpDefinitionResponse, MessageContent, MessagePart, MessageResponse, MeteredMode, MetricAggregation, MetricBucket, MetricDataPoint, MetricsOverTimeResponse, MetricsQuery, MetricsRangeQuery, MetricsStatusResponse, MetricsStoreKind, MetricsSummaryResponse, MetricType, MfaRequiredResponse, MfaSetupResponse, MfaVerificationRequest, MigrationStep, MigrationSummary, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenRequest, MintEnrollmentTokenResponse, MintEnrollmentTokenResponse2, MintEnrollmentTokenResponses, MiscResult, MkdirBody, MkdirData, MkdirErrors, MkdirResponse, MkdirResponses, ModelInfo, ModelListResponse, ModelPricing, ModelUsage, MonitoringSettings, MonitoringSettingsMasked, MonitorResponse, MonitorStatus, MrrBucketResponse, MultiNodeSettings, MultiNodeSettingsMasked, MxResult, NavEntry, NavSection, NetworkConfiguration, NetworkMode, NixpacksPresetConfig, NixpacksProvider, NodeContainerListResponse, NodeContainerResponse, NodeCostInfo, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponse, NodeHeartbeatResponses, NodeInfoResponse, NodeListResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponse, NodeMetricsGetRangeResponses, NotificationPreferencesResponse, NotificationProviderResponse, ObservabilityCompressionSettings, ObservabilityEvent, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventErrors, ObservabilityFullEventResponse, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsErrors, ObservabilityListEventsResponse, ObservabilityListEventsResponses, ObservabilityRetentionSettings, OidcCallbackData, OidcProviderResponse, OidcProvidersListResponse, OidcProviderSummary, OidcProviderUserResponse, OidcRoleMappingResponse, OidcTestConnectionResponse, OnDemandCertAttemptResponse, OnDemandCertRow, OnDemandTlsSettings, OpenAiError, OpenAiErrorResponse, OperatingSystemCount, OperationResultResponse, OperationResultsResponse, OtelDashboardResponse, OtelDashboardsResponse, OtelMetricAlertRuleResponse, OtelMetricAlertsResponse, OtelMetricLabelKeysResponse, OtelMetricLabelValuesResponse, OtelMetricNamesResponse, OtelMetricsResponse, OutlierAlgorithm, OutlierParams, OverprovisioningAssessment, OverprovisioningVerdict, PageActivityBucket, PageCountryStats, PageFlowEntry, PageFlowQuery, PageFlowResponse, PageHourlySessionsQuery, PageHourlySessionsResponse, PagePathDetailQuery, PagePathDetailResponse, PagePathInfo, PagePathSparkline, PagePathSparklinePoint, PagePathsQuery, PagePathsResponse, PagePathsSparklineQuery, PagePathsSparklineResponse, PagePathVisitorsQuery, PagePathVisitorsResponse, PageReferrerStats, PagesComparisonResponse, PageSessionComparison, PageSessionStats, PageSessionStatsQuery, PageTransition, PageVisit, PageVisitorSession, PaginatedEmailsResponse, PaginatedEntitiesResponse, PaginatedErrorEventsResponse, PaginatedErrorGroupsResponse, PaginatedEventsResponse, PaginatedExternalImagesResponse, PaginatedProjectList, PaginatedStaticBundlesResponse, Pagination, PaginationMeta, PaginationParams, PasswordProtectionConfig, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponse, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PatchPreviewGatewaySettingsResponses, PatchSettingsRequest, PathVisitors, PathVisitorsAnalyticsQuery, PathVisitorsResponse, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponse, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponse, PauseSandboxResponses, PeerEntry, PeerListResponse, PendingActionResponse, PerformanceMetricsQuery, PerformanceMetricsResponse, PermissionInfo, PgUpgradeLogResponse, PgUpgradeResponse, PipelineStats, PipelineStatsResponse, PlanComplexity, PlanMetadata, PlanRestoreData, PlanRestoreError, PlanRestoreErrors, PlanRestoreResponse, PlanRestoreResponses, PlanSourceBackup, PlanTarget, PlatformInfo, PluginManifest, PortMapping, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponse, PostDnsAckResponses, PostgresWalHealth, PresetConfigSchema, PresetInfo, PresetResponse, PreviewAlertData, PreviewAlertError, PreviewAlertErrors, PreviewAlertResponse, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponse, PreviewFunnelMetricsResponses, PreviewGatewaySettings, PreviewGatewaySettingsMasked, PreviewGatewaySettingsResponse, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponse, PreviewHostnameModeResponses, PricingResponse, ProblemDetails, ProjectConfiguration, ProjectDashboardAnalytics, ProjectDsnResponse, ProjectHealthSummary, ProjectInfo, ProjectMonitorHealth, ProjectPresetResponse, ProjectQuery, ProjectRef, ProjectResponse, ProjectSecretEnvironmentInfo, ProjectSecretResponse, ProjectServiceInfo, ProjectsHealthResponse, ProjectsMonitorHealthResponse, ProjectStatisticsResponse, ProjectStatsBreakdown, ProjectType, ProjectUsageInfoResponse, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentRequest, PromoteDeploymentResponse, PromoteDeploymentResponses, PropertyBreakdownItem, PropertyBreakdownQuery, PropertyBreakdownResponse, PropertyColumn, PropertyTimelineItem, PropertyTimelineQuery, PropertyTimelineResponse, Protocol, ProviderCatalogDto, ProviderCatalogResponse, ProviderConfig, ProviderConfigMasked, ProviderDeletionCheckResponse, ProviderDescriptor, ProviderKeyResponse, ProviderMetadata, ProviderResponse, ProviderUsage, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponse, ProvisionDomainResponses, ProvisionResponse, ProxyLogResponse, ProxyLogsPaginatedResponse, ProxyRequest, PublicHostnameStrategy, PublicPresetResponse, PublicRepositoryInfo, PurgeLogsRequest, PurgeProjectLogsData, PurgeProjectLogsError, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushedExternalImageResponse, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponse, PushExternalImageResponses, PushImageRequest, QueryDataData, QueryDataErrors, QueryDataRequest, QueryDataResponse, QueryDataResponse2, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesErrors, QueryGenaiTracesResponse, QueryGenaiTracesResponses, QueryLogsData, QueryLogsError, QueryLogsErrors, QueryLogsResponse, QueryLogsResponses, QueryMetricsData, QueryMetricsError, QueryMetricsErrors, QueryMetricsResponse, QueryMetricsResponses, QueryTracesData, QueryTracesError, QueryTracesErrors, QueryTracesResponse, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesErrors, QueryTraceSummariesResponse, QueryTraceSummariesResponses, QuotaResponse, RateLimitConfig, RateLimitSettings, ReachabilityStatus, ReadFileData, ReadFileErrors, ReadFileResponse, ReadFileResponse2, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RebuildSandboxImageData, RebuildSandboxImageErrors, RebuildSandboxImageResponses, RecentActivityQuery, RecentActivityResponse, RecentEventResponse, RecentQueryParams, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponse, RecordEventMetricsResponses, RecordListResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsErrors, RecordSpeedMetricsResponse, RecordSpeedMetricsResponses, RecoveryTarget, ReferrerCount, ReferrersAnalyticsQuery, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponse, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnRequest, RegenerateDsnResponse, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponse, RegisterExternalImageResponses, RegisterImageRequest, RegisterNodeApiRequest, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponse, RegisterNodeResponse2, RegisterNodeResponses, RegisterRequest, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponse, ReinstallGitlabWebhookResponses, ReinstallWebhookResponse, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponse, RejectPendingActionResponses, ReleaseListResponse, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponse, ReloadPluginsResponses, ReloadResponse, RemoteDeploymentResponse, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponse, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponse, RemoveManagedDomainResponses, RemoveNodeResponse, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponse, RemoveRoleResponses, RenameConversationData, RenameConversationErrors, RenameConversationRequest, RenameConversationResponse, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponse, RenewDomainResponses, RepositoryListQuery, RepositoryListResponse, RepositoryPresetResponse, RepositoryResponse, RepositorySyncStartedResponse, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponse, RequestPasswordResetResponses, RequestRow, ResetPasswordData, ResetPasswordErrors, ResetPasswordRequest, ResetPasswordResponse, ResetPasswordResponses, ResizeSandboxBody, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponse, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, ResolvedEnvVarResponse, ResolvedEnvVarSource, ResourceCounts, ResourceFootprint, ResourceInfo, ResourceLimitApplyResult, ResourceLimits, ResourceLimitsResponse, ResourceLimitsUpdateResponse, ResourcesBody, RestartContainerData, RestartContainerErrors, RestartContainerResponse, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponse, RestartSandboxResponses, RestoreCapabilities, RestoreCapabilitiesResponse, RestorePlan, RestoreRequestMode, RestoreRunView, RestoreUserData, RestoreUserErrors, RestoreUserResponse, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponse, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponse, ResumeSandboxResponses, RetentionCleanupFailure, RetentionCleanupReport, RetryClusterData, RetryClusterErrors, RetryClusterRequest, RetryClusterResponse, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponse, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponse, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponse, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponse, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponse, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponse, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponse, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponse, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponse, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponse, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponse, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueRotateTokenResponses, RevenueRow, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponse, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponse, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponse, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponse, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponse, RevokeJoinTokenResponses, RiskLevel, RoleInfo, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponse, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponse, RollbackToDeploymentResponses, RootfsCacheEntry, RootfsGcData, RootfsGcReport, RootfsGcResponses, RootfsReport, RootfsReportData, RootfsReportResponses, RootfsVmEntry, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponse, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponse, RotateDeploymentTokenResponses, RouteRefreshResponse, RouteResponse, RouteRole, RouteUser, RouteUserWithRoles, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceErrors, RunBackupForSourceResponse, RunBackupForSourceResponses, RunBackupRequest, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponse, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupErrors, RunExternalServiceBackupRequest, RunExternalServiceBackupResponse, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowError, RunScheduleNowErrors, RunScheduleNowResponse, RunScheduleNowResponses, S3ConnectionTestResponse, S3CredentialsResponse, S3SourceResponse, S3SourceResponseWritable, SandboxDomainResponse, SandboxEvent, SandboxEventsResponse, SandboxInner, SandboxResponse, SandboxRoute, SandboxStatusResponse, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenRequest, SaveAgentTokenResponse, SaveAgentTokenResponse2, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponse, SaveAiProviderCredentialResponses, SaveCredentialRequest, SaveCredentialResponse, ScalewayCredentialsRequest, ScanResponse, ScheduleRunEntry, ScheduleRunJobEntry, ScheduleRunListResponse, ScheduleRunResponse, ScheduleRunSummary, ScheduleRunSummaryList, ScreenshotSettings, SearchLogsData, SearchLogsError, SearchLogsErrors, SearchLogsRequest, SearchLogsResponse, SearchLogsResponse2, SearchLogsResponses, SearchMode, Seasonality, SecretResponse, SecurityConfig, SecurityHeadersConfig, SecurityHeadersSettings, SendEmailData, SendEmailErrors, SendEmailRequestBody, SendEmailResponse, SendEmailResponseBody, SendEmailResponses, SendMessageData, SendMessageErrors, SendMessageRequest, SendMessageResponses, SensitiveConfigValueResponse, SensitiveMcpConfigValueResponse, SensitiveValueResponse, SentryChunkUploadResponse, SentryCreateReleaseRequest, SentryEventRequest, SentryEventResponse, SentryReleaseFileResponse, SentryReleaseProjectRef, SentryReleaseResponse, SeriesStateEntry, ServiceAccessInfo, ServiceAction, ServiceAlertRuleResponse, ServiceBackupEntryResponse, ServiceBackupListResponse, ServiceCreateAlertRuleRequest, ServiceHealthResponse, ServiceHealthStatusBatchResponse, ServiceHealthStatusEntryResponse, ServiceMemberInfo, ServiceParameter, ServicePlan, ServiceResourceLimits, ServiceRuntimeReport, ServiceStatsReport, ServiceTypeInfo, ServiceTypeRoute, ServiceUpdateAlertRuleRequest, SesCredentialsRequest, SessionDetails, SessionDetailsQuery, SessionEvent, SessionEventDto, SessionEventsQuery, SessionEventsResponse, SessionLogsQuery, SessionLogsResponse, SessionReplayEventsRequest, SessionReplayInfoDto, SessionReplayInitRequest, SessionReplayInitResponse, SessionReplayWithEventsDto, SessionReplayWithVisitorDto, SessionRequestLog, SessionSummary, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceErrors, SetDefaultS3SourceResponse, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentRequest, SetFlagEnvironmentResponse, SetFlagEnvironmentResponses, SetPreviewPasswordBody, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponse, SetPreviewPasswordResponse2, SetPreviewPasswordResponses, SetRequest, SetResponse, SettingsUpdateResponse, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeRequest, SetupDnsChallengeResponse, SetupDnsChallengeResponse2, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsRequest, SetupDnsResponse, SetupDnsResponse2, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponse, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponse, SetupMfaResponses, SiblingRef, SkillDefinitionResponse, SlackConfig, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponse, SleepEnvironmentResponses, SlowQueriesResponse, SlowQueryRow, SmartFilter, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponse, SmokeTestAgentResponses, SmokeTestResponse, SmtpCredentialsRequest, SmtpEncryptionRoute, SmtpResult, SourceBackupEntry, SourceBackupIndexResponse, SourceBody, SourceFileListResponse, SourceFileResponse, SourceMapListResponse, SourceMapResponse, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponse, SourceSandboxResponses, SourceType, SpanEvent, SpanKind, SpanRecord, SpanRow, SpanStatusCode, SpeedMetricsPayload, SpeedSegmentFilters, StaleSlot, StartAnalysisData, StartAnalysisErrors, StartAnalysisRequest, StartAnalysisResponse, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponse, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeRequest, StartPgUpgradeResponse, StartPgUpgradeResponses, StartRestoreData, StartRestoreError, StartRestoreErrors, StartRestoreRequest, StartRestoreResponse, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponse, StartServiceResponses, StaticBundleResponse, StaticParams, StaticPresetConfig, StatPathData, StatPathErrors, StatPathResponse, StatPathResponses, StatResponse, StatsFilters, StatusBucket, StatusBucketedResponse, StatusCodeCount, StatusCodesQuery, StatusPageOverview, StepConversionResponse, StepResourceType, StepResult, StopContainerData, StopContainerErrors, StopContainerResponse, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponse, StopSandboxResponses, StopSequence, StopServiceData, StopServiceErrors, StopServiceResponse, StopServiceResponses, StorageQuota, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, StripeConfig, SyncedRepositoryListQuery, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponse, SyncRepositoriesResponses, SyntaxResult, TagInfo, TagListResponse, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsError, TailLogsErrors, TailLogsRequest, TailLogsResponses, TargetRecommendation, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponse, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponse, TeardownEnvironmentResponses, TemplateResponse, TestEmailRequest, TestEmailResponse, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponse, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponse, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponse, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdErrors, TestProviderKeyByIdResponse, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineErrors, TestProviderKeyInlineResponse, TestProviderKeyInlineResponses, TestProviderKeyRequest, TestProviderKeyResponse, TestProviderResponse, TestProviderResponse2, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponse, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionErrors, TestS3SourceConnectionResponse, TestS3SourceConnectionResponses, TimeBucketStats, TimeBucketStatsResponse, TimeseriesBucket, TimeseriesQueryParams, TlsMode, TodayStatsResponse, ToggleDeploymentMetricsRequest, ToggleServiceMetricsRequest, TokenRenewalRequest, ToolCallEvent, ToolInfo, ToolResultEvent, TopModelsQueryParams, TraceProjectRef, TracesResponse, TraceSummariesResponse, TraceSummary, TrackClickData, TrackClickErrors, TrackedLinkResponse, TrackingEventResponse, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentRequest, TriggerAgentResponse, TriggerAgentResponses, TriggerDigestResponse, TriggerPipelinePayload, TriggerPipelineResponse, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponse, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanError, TriggerScanErrors, TriggerScanRequest, TriggerScanResponse, TriggerScanResponse2, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponse, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponse, TriggerWeeklyDigestResponses, TtlRequest, TtlResponse, TxtRecord, UiManifest, UiRoute, UndrainNodeResponse, UnifiedTrace, UniqueCountsQuery, UniqueCountsResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponse, UnlinkServiceFromProjectResponses, UnsupportedFeature, UpdateAdminGateRequest, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderRequest, UpdateAiProviderResponse, UpdateAiProviderResponse2, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertError, UpdateAlertErrors, UpdateAlertResponse, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleRequest, UpdateAlertRuleResponse, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyRequest, UpdateApiKeyResponse, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployRequest, UpdateAutomaticDeployResponse, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleErrors, UpdateBackupScheduleRequest, UpdateBackupScheduleResponse, UpdateBackupScheduleResponses, UpdateBlobRequest, UpdateBlobResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderRequest, UpdateCloudflareProviderResponse, UpdateCloudflareProviderResponses, UpdateConfigBody, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponse, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainRequest, UpdateCustomDomainResponse, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardError, UpdateDashboardErrors, UpdateDashboardRequest, UpdateDashboardResponse, UpdateDashboardResponses, UpdateDeploymentConfigRequest, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenRequest, UpdateDeploymentTokenResponse, UpdateDeploymentTokenResponses, UpdateDnsProviderRequest, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderRequest, UpdateEmailProviderResponse, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsRequest, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainRequest, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableRequest, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupRequest, UpdateErrorGroupResponses, UpdateExternalServiceRequest, UpdateFlagData, UpdateFlagErrors, UpdateFlagRequest, UpdateFlagResponse, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponse, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsRequest, UpdateGitSettingsResponse, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponse, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponse, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusRequest, UpdateIncidentStatusResponse, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlErrors, UpdateIpAccessControlRequest, UpdateIpAccessControlResponse, UpdateIpAccessControlResponses, UpdateKvRequest, UpdateKvResponse, UpdateManagedDomainApiRequest, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponse, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpRequest, UpdateMcpResponse, UpdateMcpResponses, UpdateMetricAlertRequest, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderRequest, UpdateNotificationEmailProviderResponse, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponse, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderRequest, UpdateOidcProviderResponse, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesRequest, UpdatePreferencesResponse, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponse, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretRequest, UpdateProjectSecretResponse, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsRequest, UpdateProjectSettingsResponse, UpdateProjectSettingsResponses, UpdateProviderCredentialsRequest, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyErrors, UpdateProviderKeyRequest, UpdateProviderKeyResponse, UpdateProviderKeyResponses, UpdateProviderRequest, UpdateProviderResponse, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteRequest, UpdateRouteResponse, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceErrors, UpdateS3SourceRequest, UpdateS3SourceResponse, UpdateS3SourceResponses, UpdateSecretBody, UpdateSelfData, UpdateSelfErrors, UpdateSelfRequest, UpdateSelfResponse, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponse, UpdateServiceResourcesResponses, UpdateServiceResponse, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationErrors, UpdateSessionDurationRequest, UpdateSessionDurationResponse, UpdateSessionDurationResponse2, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponse, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillRequest, UpdateSkillResponse, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderRequest, UpdateSlackProviderResponse, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsErrors, UpdateSpeedMetricsPayload, UpdateSpeedMetricsResponse, UpdateSpeedMetricsResponses, UpdateStatusResponse, UpdateTokenRequest, UpdateTokenResponse, UpdateUserData, UpdateUserErrors, UpdateUserRequest, UpdateUserResponse, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderRequest, UpdateWebhookProviderResponse, UpdateWebhookProviderResponses, UpdateWebhookRequestBody, UpdateWebhookResponse, UpdateWebhookResponses, UpgradeExternalServiceRequest, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradePreviewGatewayResponses, UpgradeRequest, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponse, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponse, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponse, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponse, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponse, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponse, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponse, UploadStaticBundleResponses, UpsertAgentRequest, UpsertSecretData, UpsertSecretErrors, UpsertSecretRequest, UpsertSecretResponse, UpsertSecretResponses, UptimeDataPoint, UptimeHistoryResponse, UsageFilter, UsageInfo, UsageLogEntry, UsageLogPage, UsageQueryParams, UsageSource, UsageSummary, UserResponse, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponse, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailRequest, ValidateEmailResponse, ValidateEmailResponse2, ValidateEmailResponses, ValidationLevel, ValidationReport, ValidationResponse, ValidationResult, ValidationStatus, ValidationSummary, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponse, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponse, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponse, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponse, VerifyMfaChallengeResponses, VerifyMfaRequest, ViewItem, ViewsOverTime, ViewsOverTimeQuery, VisitorDetails, VisitorFacets, VisitorFacetsQuery, VisitorFacetValue, VisitorInfo, VisitorJourneyQuery, VisitorJourneyResponse, VisitorLocationsQuery, VisitorRecord, VisitorSegmentFilters, VisitorSessionsQuery, VisitorSessionsResponse, VisitorsListQuery, VisitorsResponse, VisitorStats, VisitorWithGeolocation, VolumeMount, VolumeType, VulnerabilityResponse, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponse, WakeEnvironmentResponses, WalWarning, WalWarningSeverity, WebhookConfig, WebhookDeliveryResponse, WebhookResponse, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerRequest, WebhookTriggerResponse, WebhookTriggerResponse2, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunRequest, WorkflowDryRunResponse, WorkflowDryRunResponses, WorkloadDescriptor, WorkloadId, WorkloadStatus, WorkloadType, WriteFileBody, WriteFileData, WriteFileErrors, WriteFileResponse, WriteFileResponses, WriteFilesBody, WriteFilesData, WriteFilesErrors, WriteFilesResponse, WriteFilesResponse2, WriteFilesResponses, ZoneListResponse } from './types.gen'; diff --git a/apps/temps-cli/src/api/sdk.gen.ts b/apps/temps-cli/src/api/sdk.gen.ts index 31fb99c8d..f94c2c3bd 100644 --- a/apps/temps-cli/src/api/sdk.gen.ts +++ b/apps/temps-cli/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import { type Client, type ClientMeta, formDataBodySerializer, type Options as Options2, type RequestResult, type ServerSentEventsResult, type TDataShape } from './client'; import { client } from './client.gen'; -import type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponses, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainResponses, AddEventsData, AddEventsErrors, AddEventsResponses, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsErrors, AddSessionReplayEventsResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponses, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponses, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeResponses, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponses, AssignRoleData, AssignRoleErrors, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesErrors, AttachScheduleServicesResponses, BlobCopyData, BlobCopyErrors, BlobCopyResponses, BlobDeleteData, BlobDeleteErrors, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponses, BlobDownloadData, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponses, BlobHeadData, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListErrors, BlobListResponses, BlobPutData, BlobPutErrors, BlobPutResponses, BlobStatusData, BlobStatusErrors, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponses, CancelBackupData, CancelBackupErrors, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunErrors, CancelScheduleRunResponses, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceResponses, ChatCompletionsData, ChatCompletionsErrors, ChatCompletionsResponses, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponses, ChunkUploadOptionsData, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsErrors, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartResponses, CliLogoutData, CliLogoutErrors, CliLogoutResponses, CmdData, CmdErrors, CmdKillData, CmdKillErrors, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponses, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponses, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponses, CreateAgentData, CreateAgentErrors, CreateAgentResponses, CreateAlertData, CreateAlertErrors, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleErrors, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponses, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardErrors, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainResponses, CreateDsnData, CreateDsnErrors, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelResponses, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponses, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponses, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponses, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponses, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponses, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentResponses, CreateIpAccessControlData, CreateIpAccessControlErrors, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpResponses, CreateMonitorData, CreateMonitorErrors, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponses, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyErrors, CreateProviderKeyResponses, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteResponses, CreateS3SourceData, CreateS3SourceErrors, CreateS3SourceResponses, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderResponses, CreateUserData, CreateUserErrors, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderResponses, CreateWebhookResponses, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponses, DeleteAlertData, DeleteAlertErrors, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupErrors, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleErrors, DeleteBackupScheduleResponses, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardErrors, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlErrors, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyErrors, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponses, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceErrors, DeleteS3SourceResponses, DeleteScanData, DeleteScanErrors, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponses, DeployFromImageData, DeployFromImageErrors, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticResponses, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceErrors, DetachScheduleServiceResponses, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponses, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponses, DisableMfaData, DisableMfaErrors, DisableMfaResponses, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponses, DomainData, DomainErrors, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponses, EmailStatusData, EmailStatusErrors, EmailStatusResponses, EmbeddingsData, EmbeddingsErrors, EmbeddingsResponses, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponses, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorResponses, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponses, ExecErrors, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportResponses, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponses, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponses, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponses, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponses, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesErrors, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineErrors, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownErrors, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponses, GetAlertData, GetAlertErrors, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponses, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponses, GetBackupData, GetBackupErrors, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailErrors, GetConversationDetailResponses, GetConversationErrors, GetConversationResponses, GetConversationsData, GetConversationsErrors, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponses, GetDashboardData, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponses, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponses, GetDeploymentResponses, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponses, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponses, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceErrors, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponses, GetHealthData, GetHealthErrors, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlErrors, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationErrors, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanErrors, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextErrors, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeErrors, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsErrors, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponses, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsErrors, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingErrors, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponses, GetProjectsData, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysErrors, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthErrors, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponses, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdErrors, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsErrors, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponses, GetQuotaData, GetQuotaErrors, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponses, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponses, GetRestoreCapabilitiesData, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunErrors, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceErrors, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentErrors, GetScanByDeploymentResponses, GetScanData, GetScanErrors, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsErrors, GetSessionReplayEventsResponses, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponses, GetTimeBucketStatsData, GetTimeBucketStatsErrors, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsErrors, GetTodayStatsResponses, GetTraceData, GetTraceErrors, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceErrors, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderErrors, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentErrors, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryErrors, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesErrors, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsErrors, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsErrors, GetVisitorSessionsResponses, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponses, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponses, HasPerformanceMetricsData, HasPerformanceMetricsErrors, HasPerformanceMetricsResponses, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceResponses, IngestLogsByPathData, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesErrors, IngestTracesResponses, InitSessionReplayData, InitSessionReplayErrors, InitSessionReplayResponses, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponses, KillJobData, KillJobErrors, KillJobResponses, KvDelData, KvDelErrors, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponses, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponses, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponses, ListAlertsData, ListAlertsErrors, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsErrors, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenErrors, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesErrors, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponses, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponses, ListDashboardsData, ListDashboardsErrors, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsResponses, ListEventsData, ListEventsResponses, ListEventTypesData, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsErrors, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlErrors, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsErrors, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysErrors, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesErrors, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesErrors, ListMetricNamesResponses, ListModelsData, ListModelsErrors, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansErrors, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysErrors, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponses, ListS3SourcesData, ListS3SourcesErrors, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponses, ListScheduleRunJobsData, ListScheduleRunJobsErrors, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsErrors, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesErrors, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesErrors, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsErrors, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponses, ListUsersData, ListUsersErrors, ListUsersResponses, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponses, LoginData, LoginErrors, LoginResponses, LogoutData, LogoutErrors, LogoutResponses, LookupDnsARecordsData, LookupDnsARecordsErrors, LookupDnsARecordsResponses, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenResponses, MkdirData, MkdirErrors, MkdirResponses, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponses, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponses, ObservabilityFullEventData, ObservabilityFullEventErrors, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsErrors, ObservabilityListEventsResponses, OidcCallbackData, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponses, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponses, PlanRestoreData, PlanRestoreErrors, PlanRestoreResponses, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponses, PreviewAlertData, PreviewAlertErrors, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponses, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponses, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentResponses, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponses, PurgeProjectLogsData, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponses, QueryDataData, QueryDataErrors, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesErrors, QueryGenaiTracesResponses, QueryLogsData, QueryLogsErrors, QueryLogsResponses, QueryMetricsData, QueryMetricsErrors, QueryMetricsResponses, QueryTracesData, QueryTracesErrors, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesErrors, QueryTraceSummariesResponses, ReadFileData, ReadFileErrors, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RebuildSandboxImageData, RebuildSandboxImageErrors, RebuildSandboxImageResponses, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponses, RecordSpeedMetricsData, RecordSpeedMetricsErrors, RecordSpeedMetricsResponses, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponses, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponses, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponses, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponses, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponses, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponses, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponses, RenameConversationData, RenameConversationErrors, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, ResetPasswordData, ResetPasswordErrors, ResetPasswordResponses, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, RestartContainerData, RestartContainerErrors, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponses, RestoreUserData, RestoreUserErrors, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponses, RetryClusterData, RetryClusterErrors, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponses, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponses, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponses, RootfsGcData, RootfsGcResponses, RootfsReportData, RootfsReportResponses, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponses, RunBackupForSourceData, RunBackupForSourceErrors, RunBackupForSourceResponses, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupErrors, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowErrors, RunScheduleNowResponses, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponses, SearchLogsData, SearchLogsErrors, SearchLogsResponses, SendEmailData, SendEmailErrors, SendEmailResponses, SendMessageData, SendMessageErrors, SendMessageResponses, SetDefaultS3SourceData, SetDefaultS3SourceErrors, SetDefaultS3SourceResponses, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponses, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponses, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponses, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponses, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponses, StartAnalysisData, StartAnalysisErrors, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeResponses, StartRestoreData, StartRestoreErrors, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponses, StatPathData, StatPathErrors, StatPathResponses, StopContainerData, StopContainerErrors, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponses, StopServiceData, StopServiceErrors, StopServiceResponses, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponses, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsErrors, TailLogsResponses, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponses, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdErrors, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineErrors, TestProviderKeyInlineResponses, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionErrors, TestS3SourceConnectionResponses, TrackClickData, TrackClickErrors, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentResponses, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanErrors, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponses, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponses, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertErrors, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleErrors, UpdateBackupScheduleResponses, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderResponses, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardErrors, UpdateDashboardResponses, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenResponses, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlErrors, UpdateIpAccessControlResponses, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpResponses, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsResponses, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyErrors, UpdateProviderKeyResponses, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceErrors, UpdateS3SourceResponses, UpdateSelfData, UpdateSelfErrors, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponses, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationErrors, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsErrors, UpdateSpeedMetricsResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderResponses, UpdateWebhookResponses, UpgradePreviewGatewayData, UpgradePreviewGatewayResponses, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponses, UpsertSecretData, UpsertSecretErrors, UpsertSecretResponses, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailResponses, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponses, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponses, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunResponses, WriteFileData, WriteFileErrors, WriteFileResponses, WriteFilesData, WriteFilesErrors, WriteFilesResponses } from './types.gen'; +import type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponses, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainResponses, AddEventsData, AddEventsErrors, AddEventsResponses, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsErrors, AddSessionReplayEventsResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponses, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponses, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeResponses, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponses, AssignRoleData, AssignRoleErrors, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesErrors, AttachScheduleServicesResponses, BlobCopyData, BlobCopyErrors, BlobCopyResponses, BlobDeleteData, BlobDeleteErrors, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponses, BlobDownloadData, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponses, BlobHeadData, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListErrors, BlobListResponses, BlobPutData, BlobPutErrors, BlobPutResponses, BlobStatusData, BlobStatusErrors, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponses, CancelBackupData, CancelBackupErrors, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunErrors, CancelScheduleRunResponses, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceResponses, ChatCompletionsData, ChatCompletionsErrors, ChatCompletionsResponses, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponses, ChunkUploadOptionsData, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsErrors, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartResponses, CliLogoutData, CliLogoutErrors, CliLogoutResponses, CmdData, CmdErrors, CmdKillData, CmdKillErrors, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponses, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponses, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponses, CreateAgentData, CreateAgentErrors, CreateAgentResponses, CreateAlertData, CreateAlertErrors, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleErrors, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponses, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardErrors, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainResponses, CreateDsnData, CreateDsnErrors, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableResponses, CreateFlagData, CreateFlagErrors, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelResponses, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponses, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponses, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponses, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponses, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponses, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentResponses, CreateIpAccessControlData, CreateIpAccessControlErrors, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpResponses, CreateMonitorData, CreateMonitorErrors, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponses, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyErrors, CreateProviderKeyResponses, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteResponses, CreateS3SourceData, CreateS3SourceErrors, CreateS3SourceResponses, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderResponses, CreateUserData, CreateUserErrors, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderResponses, CreateWebhookResponses, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponses, DeleteAlertData, DeleteAlertErrors, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupErrors, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleErrors, DeleteBackupScheduleResponses, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardErrors, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlErrors, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyErrors, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponses, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceErrors, DeleteS3SourceResponses, DeleteScanData, DeleteScanErrors, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponses, DeployFromImageData, DeployFromImageErrors, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticResponses, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceErrors, DetachScheduleServiceResponses, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponses, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponses, DisableMfaData, DisableMfaErrors, DisableMfaResponses, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponses, DomainData, DomainErrors, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponses, EmailStatusData, EmailStatusErrors, EmailStatusResponses, EmbeddingsData, EmbeddingsErrors, EmbeddingsResponses, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponses, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorResponses, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponses, ExecErrors, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportResponses, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponses, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponses, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponses, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponses, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesErrors, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineErrors, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownErrors, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponses, GetAlertData, GetAlertErrors, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponses, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponses, GetBackupData, GetBackupErrors, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailErrors, GetConversationDetailResponses, GetConversationErrors, GetConversationResponses, GetConversationsData, GetConversationsErrors, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponses, GetDashboardData, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponses, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponses, GetDeploymentResponses, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponses, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponses, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceErrors, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponses, GetHealthData, GetHealthErrors, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlErrors, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationErrors, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanErrors, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextErrors, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeErrors, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsErrors, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponses, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsErrors, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingErrors, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponses, GetProjectsData, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysErrors, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthErrors, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponses, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdErrors, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsErrors, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponses, GetQuotaData, GetQuotaErrors, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponses, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponses, GetRestoreCapabilitiesData, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunErrors, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceErrors, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentErrors, GetScanByDeploymentResponses, GetScanData, GetScanErrors, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsErrors, GetSessionReplayEventsResponses, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponses, GetTimeBucketStatsData, GetTimeBucketStatsErrors, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsErrors, GetTodayStatsResponses, GetTraceData, GetTraceErrors, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceErrors, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderErrors, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentErrors, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryErrors, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesErrors, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsErrors, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsErrors, GetVisitorSessionsResponses, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponses, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponses, HasPerformanceMetricsData, HasPerformanceMetricsErrors, HasPerformanceMetricsResponses, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceResponses, IngestLogsByPathData, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesErrors, IngestTracesResponses, InitSessionReplayData, InitSessionReplayErrors, InitSessionReplayResponses, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponses, KillJobData, KillJobErrors, KillJobResponses, KvDelData, KvDelErrors, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponses, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponses, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponses, ListAlertsData, ListAlertsErrors, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsErrors, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenErrors, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesErrors, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponses, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponses, ListDashboardsData, ListDashboardsErrors, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsResponses, ListEventsData, ListEventsResponses, ListEventTypesData, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsErrors, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlErrors, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsErrors, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysErrors, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesErrors, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesErrors, ListMetricNamesResponses, ListModelsData, ListModelsErrors, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansErrors, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysErrors, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponses, ListS3SourcesData, ListS3SourcesErrors, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponses, ListScheduleRunJobsData, ListScheduleRunJobsErrors, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsErrors, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesErrors, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesErrors, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsErrors, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponses, ListUsersData, ListUsersErrors, ListUsersResponses, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponses, LoginData, LoginErrors, LoginResponses, LogoutData, LogoutErrors, LogoutResponses, LookupDnsARecordsData, LookupDnsARecordsErrors, LookupDnsARecordsResponses, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenResponses, MkdirData, MkdirErrors, MkdirResponses, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponses, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponses, ObservabilityFullEventData, ObservabilityFullEventErrors, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsErrors, ObservabilityListEventsResponses, OidcCallbackData, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponses, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponses, PlanRestoreData, PlanRestoreErrors, PlanRestoreResponses, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponses, PreviewAlertData, PreviewAlertErrors, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponses, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponses, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentResponses, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponses, PurgeProjectLogsData, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponses, QueryDataData, QueryDataErrors, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesErrors, QueryGenaiTracesResponses, QueryLogsData, QueryLogsErrors, QueryLogsResponses, QueryMetricsData, QueryMetricsErrors, QueryMetricsResponses, QueryTracesData, QueryTracesErrors, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesErrors, QueryTraceSummariesResponses, ReadFileData, ReadFileErrors, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RebuildSandboxImageData, RebuildSandboxImageErrors, RebuildSandboxImageResponses, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponses, RecordSpeedMetricsData, RecordSpeedMetricsErrors, RecordSpeedMetricsResponses, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponses, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponses, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponses, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponses, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponses, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponses, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponses, RenameConversationData, RenameConversationErrors, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, ResetPasswordData, ResetPasswordErrors, ResetPasswordResponses, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, RestartContainerData, RestartContainerErrors, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponses, RestoreUserData, RestoreUserErrors, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponses, RetryClusterData, RetryClusterErrors, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponses, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponses, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponses, RootfsGcData, RootfsGcResponses, RootfsReportData, RootfsReportResponses, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponses, RunBackupForSourceData, RunBackupForSourceErrors, RunBackupForSourceResponses, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupErrors, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowErrors, RunScheduleNowResponses, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponses, SearchLogsData, SearchLogsErrors, SearchLogsResponses, SendEmailData, SendEmailErrors, SendEmailResponses, SendMessageData, SendMessageErrors, SendMessageResponses, SetDefaultS3SourceData, SetDefaultS3SourceErrors, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentResponses, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponses, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponses, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponses, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponses, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponses, StartAnalysisData, StartAnalysisErrors, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeResponses, StartRestoreData, StartRestoreErrors, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponses, StatPathData, StatPathErrors, StatPathResponses, StopContainerData, StopContainerErrors, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponses, StopServiceData, StopServiceErrors, StopServiceResponses, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponses, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsErrors, TailLogsResponses, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponses, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdErrors, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineErrors, TestProviderKeyInlineResponses, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionErrors, TestS3SourceConnectionResponses, TrackClickData, TrackClickErrors, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentResponses, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanErrors, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponses, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponses, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertErrors, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleErrors, UpdateBackupScheduleResponses, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderResponses, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardErrors, UpdateDashboardResponses, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenResponses, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupResponses, UpdateFlagData, UpdateFlagErrors, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlErrors, UpdateIpAccessControlResponses, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpResponses, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsResponses, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyErrors, UpdateProviderKeyResponses, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceErrors, UpdateS3SourceResponses, UpdateSelfData, UpdateSelfErrors, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponses, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationErrors, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsErrors, UpdateSpeedMetricsResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderResponses, UpdateWebhookResponses, UpgradePreviewGatewayData, UpgradePreviewGatewayResponses, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponses, UpsertSecretData, UpsertSecretErrors, UpsertSecretResponses, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailResponses, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponses, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponses, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunResponses, WriteFileData, WriteFileErrors, WriteFileResponses, WriteFilesData, WriteFilesErrors, WriteFilesResponses } from './types.gen'; export type Options = Options2 & { /** @@ -2688,6 +2688,24 @@ export const getFile = (options: Options(options?: Options): RequestResult => (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/flags/snapshot', + ...options +}); + /** * Get geolocation information for an IP address */ @@ -5624,6 +5642,57 @@ export const getRemoteExternalImage = (opt ...options }); +export const listFlags = (options: Options): RequestResult => (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags', + ...options +}); + +export const createFlag = (options: Options): RequestResult => (options.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + +export const archiveFlag = (options: Options): RequestResult => (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags/{key}', + ...options +}); + +export const getFlag = (options: Options): RequestResult => (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags/{key}', + ...options +}); + +export const updateFlag = (options: Options): RequestResult => (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags/{key}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + +/** + * Set a flag's value in one environment, and/or flip its kill switch. + */ +export const setFlagEnvironment = (options: Options): RequestResult => (options.client ?? client).put({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags/{key}/environments/{environment_id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + /** * List all funnels for a project */ diff --git a/apps/temps-cli/src/api/types.gen.ts b/apps/temps-cli/src/api/types.gen.ts index 7924f31bd..0eda76dcf 100644 --- a/apps/temps-cli/src/api/types.gen.ts +++ b/apps/temps-cli/src/api/types.gen.ts @@ -1160,6 +1160,11 @@ export type ApplyHostnameModeRequest = { sync_dns?: boolean; }; +export type ArchiveFlagResponse = { + archived_at?: string | null; + key: string; +}; + export type ArchiveMode = 'off' | 'on' | 'always' | 'unknown'; export type AssignRoleRequest = { @@ -3260,6 +3265,33 @@ export type CreateExternalServiceRequest = { version?: string | null; }; +export type CreateFlagRequest = { + /** + * Whether the flag may be exposed on the unauthenticated same-origin + * evaluation endpoint. Defaults to `false`: flags are server-only unless + * explicitly opted in, because targeting rules can encode business logic. + */ + client_visible?: boolean; + /** + * Served whenever evaluation cannot do better. Must match `value_type`. + * + * Left unannotated so utoipa emits a free-form schema: a bool flag's + * default is `false`, not an object, and `value_type = Object` would tell + * every generated client otherwise. + */ + default_value: unknown; + description?: string | null; + /** + * Stable key used in application code. Immutable after create. + */ + key: string; + /** + * Fixed at create: retyping would invalidate every stored value and every + * call site. + */ + value_type: FlagValueType; +}; + export type CreateFunnelRequest = { description?: string | null; name: string; @@ -4274,6 +4306,27 @@ export type DeploymentConfig = { * `n / 1_000_000` cores into Docker nano_cpus. */ cpuRequest?: number | null; + /** + * Build one image per architecture the eligible nodes run. + * + * `None`/`false` (the default) builds exactly once, on the control + * plane's native platform — byte-for-byte the behaviour of a + * single-architecture cluster. When enabled and the nodes this + * deployment could land on span more than one architecture, the build + * job produces one image per architecture; the non-native ones go + * through the daemon's `platform` option, which requires QEMU binfmt + * handlers registered on the control plane. + * + * **Opt-in on purpose.** Cross-architecture builds are emulated and + * substantially slower, and deriving them from cluster topology would + * mean a single node joining silently changes build behaviour for every + * deployment in the cluster. It also keeps the decision on operator + * config rather than on a value each node reports about itself. + * + * `Option` so an environment inherits the project's setting + * (`None`) or overrides it, matching `automatic_deploy`. + */ + crossArchitectureBuilds?: boolean | null; /** * Port exposed by the container * If not specified, will be auto-detected from Docker image or default to 3000 @@ -6985,6 +7038,80 @@ export type FiringSeriesEntry = { series_label: string; }; +export type FlagEnvironmentResponse = { + enabled: boolean; + environment_id: number; + value?: unknown; +}; + +/** + * Note the absence of `salt`: it is never exposed. Publishing the bucketing + * salt would let a client predict, and self-select into, a rollout cohort. + */ +export type FlagListResponse = { + flags: Array; + page: number; + page_size: number; + /** + * Total flags matching the filter, across all pages. + */ + total: number; + total_pages: number; +}; + +export type FlagResponse = { + archived_at?: string | null; + client_visible: boolean; + created_at: string; + default_value: unknown; + description?: string | null; + /** + * Per-environment overrides. Empty means the flag inherits its default + * everywhere. + */ + environments: Array; + id: number; + key: string; + updated_at: string; + value_type: string; +}; + +/** + * A single flag, already resolved down to one environment. This is what the + * evaluator sees and what the SDK caches in memory. + */ +export type FlagSnapshot = { + /** + * Served whenever evaluation cannot do better. Genuinely polymorphic by + * design — the surrounding struct carries the type. + */ + default_value: unknown; + /** + * False means the kill switch is engaged for this environment. + */ + enabled: boolean; + /** + * `None` means "inherit `default_value`". + */ + environment_value?: unknown; + key: string; + value_type: FlagValueType; +}; + +export type FlagSnapshotResponse = { + environment_id: number; + /** + * Flags collapsed to what the evaluator needs, sorted by key so the + * serialized form — and therefore the ETag — is stable. + */ + flags: Array; +}; + +/** + * The declared type of a flag's value. Fixed at create time. + */ +export type FlagValueType = 'bool' | 'string' | 'number' | 'json'; + /** * Forecast model family. */ @@ -7957,6 +8084,12 @@ export type HealthSummary = { }; export type HeartbeatApiRequest = { + /** + * Container platform of this node's Docker daemon (`linux/amd64`, + * `linux/arm64`), read from `docker info` by the agent. Absent from + * pre-multi-arch agents; the stored value is then left untouched. + */ + architecture?: string | null; /** * Resource capacity/usage info as JSON (cpu_usage, memory_usage, etc.) */ @@ -10047,6 +10180,11 @@ export type NodeCostInfo = { export type NodeInfoResponse = { address: string; + /** + * Container platform this node runs (`linux/amd64`, `linux/arm64`). + * `None` until an agent that reports it has heartbeated. + */ + architecture?: string | null; /** * Resource capacity/usage metrics from the latest heartbeat */ @@ -12760,6 +12898,12 @@ export type RegisterNodeApiRequest = { * Node's reachable address (e.g., "10.100.0.2" or "192.168.1.50") */ address: string; + /** + * Container platform of this node's Docker daemon (`linux/amd64`, + * `linux/arm64`). Optional: agents older than multi-arch support omit it + * and the value is learned from the first heartbeat instead. + */ + architecture?: string | null; /** * Node-generated certificate signing request (PEM) for multi-node mTLS * (ADR-020 WS-2.1). When present, the control plane signs it with the @@ -14842,6 +14986,19 @@ export type SessionSummary = { started_at: string; }; +export type SetFlagEnvironmentRequest = { + /** + * The kill switch. `false` makes the flag serve its default regardless of + * any override — and, once targeting exists, regardless of any rule. + */ + enabled?: boolean | null; + /** + * Tri-state: absent leaves the override, `null` clears it (inherit the + * flag default), anything else sets it. Must match `value_type`. + */ + value?: unknown; +}; + export type SetPreviewPasswordBody = { /** * Plaintext password to protect the sandbox's preview URLs. Hashed @@ -16765,6 +16922,13 @@ export type UpdateDeploymentConfigRequest = { automaticDeploy?: boolean | null; cpuLimit?: number | null; cpuRequest?: number | null; + /** + * Build one image per architecture the eligible nodes run. Off by + * default; environments inherit this and may override it. Cross-builds + * are emulated on the control plane and substantially slower, so they are + * opted into rather than triggered by cluster topology. + */ + crossArchitectureBuilds?: boolean | null; exposedPort?: number | null; memoryLimit?: number | null; memoryRequest?: number | null; @@ -16852,6 +17016,13 @@ export type UpdateEnvironmentSettingsRequest = { * Absent leaves the current value unchanged. */ cpu_request?: number | null; + /** + * Build one image per architecture the eligible nodes run (overrides the + * project-level setting). Off by default: cross-architecture builds are + * emulated on the control plane and substantially slower, so they are + * opted into per environment rather than triggered by cluster topology. + */ + cross_architecture_builds?: boolean | null; /** * Port exposed by the container (overrides project-level port for this environment) * @@ -16985,6 +17156,18 @@ export type UpdateExternalServiceRequest = { }; }; +export type UpdateFlagRequest = { + client_visible?: boolean | null; + /** + * Must match the flag's existing `value_type`. + */ + default_value?: unknown; + /** + * Tri-state: absent leaves it, `null` clears it, a string sets it. + */ + description?: string | null; +}; + export type UpdateGitSettingsRequest = { directory: string; git_provider_connection_id?: number | null; @@ -28520,6 +28703,47 @@ export type GetFileResponses = { export type GetFileResponse = GetFileResponses[keyof GetFileResponses]; +export type GetFlagSnapshotData = { + body?: never; + path?: never; + query?: { + /** + * Required only when the calling token is project-wide rather than scoped + * to a single environment. + */ + environment_id?: number | null; + }; + url: '/flags/snapshot'; +}; + +export type GetFlagSnapshotErrors = { + /** + * Environment could not be determined + */ + 400: unknown; + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type GetFlagSnapshotResponses = { + /** + * Snapshot for the environment + */ + 200: FlagSnapshotResponse; +}; + +export type GetFlagSnapshotResponse = GetFlagSnapshotResponses[keyof GetFlagSnapshotResponses]; + export type GetIpGeolocationData = { body?: never; path: { @@ -40390,6 +40614,287 @@ export type GetRemoteExternalImageResponses = { export type GetRemoteExternalImageResponse = GetRemoteExternalImageResponses[keyof GetRemoteExternalImageResponses]; +export type ListFlagsData = { + body?: never; + path: { + /** + * Project ID + */ + project_id: number; + }; + query?: { + /** + * Include archived flags. Defaults to false. + */ + include_archived?: boolean; + /** + * 1-indexed page number. Defaults to 1. + */ + page?: number | null; + /** + * Items per page. Defaults to 20, capped at 100. + */ + page_size?: number | null; + }; + url: '/projects/{project_id}/flags'; +}; + +export type ListFlagsErrors = { + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type ListFlagsResponses = { + /** + * Flags listed + */ + 200: FlagListResponse; +}; + +export type ListFlagsResponse = ListFlagsResponses[keyof ListFlagsResponses]; + +export type CreateFlagData = { + body: CreateFlagRequest; + path: { + /** + * Project ID + */ + project_id: number; + }; + query?: never; + url: '/projects/{project_id}/flags'; +}; + +export type CreateFlagErrors = { + /** + * Validation error + */ + 400: unknown; + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag key already exists + */ + 409: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type CreateFlagResponses = { + /** + * Flag created + */ + 201: FlagResponse; +}; + +export type CreateFlagResponse = CreateFlagResponses[keyof CreateFlagResponses]; + +export type ArchiveFlagData = { + body?: never; + path: { + /** + * Project ID + */ + project_id: number; + /** + * Flag key + */ + key: string; + }; + query?: never; + url: '/projects/{project_id}/flags/{key}'; +}; + +export type ArchiveFlagErrors = { + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag not found + */ + 404: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type ArchiveFlagResponses = { + /** + * Flag archived + */ + 200: ArchiveFlagResponse; +}; + +export type ArchiveFlagResponse2 = ArchiveFlagResponses[keyof ArchiveFlagResponses]; + +export type GetFlagData = { + body?: never; + path: { + /** + * Project ID + */ + project_id: number; + /** + * Flag key + */ + key: string; + }; + query?: never; + url: '/projects/{project_id}/flags/{key}'; +}; + +export type GetFlagErrors = { + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag not found + */ + 404: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type GetFlagResponses = { + /** + * Flag retrieved + */ + 200: FlagResponse; +}; + +export type GetFlagResponse = GetFlagResponses[keyof GetFlagResponses]; + +export type UpdateFlagData = { + body: UpdateFlagRequest; + path: { + /** + * Project ID + */ + project_id: number; + /** + * Flag key + */ + key: string; + }; + query?: never; + url: '/projects/{project_id}/flags/{key}'; +}; + +export type UpdateFlagErrors = { + /** + * Validation error + */ + 400: unknown; + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag not found + */ + 404: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type UpdateFlagResponses = { + /** + * Flag updated + */ + 200: FlagResponse; +}; + +export type UpdateFlagResponse = UpdateFlagResponses[keyof UpdateFlagResponses]; + +export type SetFlagEnvironmentData = { + body: SetFlagEnvironmentRequest; + path: { + /** + * Project ID + */ + project_id: number; + /** + * Flag key + */ + key: string; + /** + * Environment ID + */ + environment_id: number; + }; + query?: never; + url: '/projects/{project_id}/flags/{key}/environments/{environment_id}'; +}; + +export type SetFlagEnvironmentErrors = { + /** + * Validation error + */ + 400: unknown; + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag or environment not found + */ + 404: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type SetFlagEnvironmentResponses = { + /** + * Environment value set + */ + 200: FlagEnvironmentResponse; +}; + +export type SetFlagEnvironmentResponse = SetFlagEnvironmentResponses[keyof SetFlagEnvironmentResponses]; + export type ListFunnelsData = { body?: never; path: { diff --git a/apps/temps-cli/src/cli.ts b/apps/temps-cli/src/cli.ts index f001a2e9b..c33a128a2 100644 --- a/apps/temps-cli/src/cli.ts +++ b/apps/temps-cli/src/cli.ts @@ -30,6 +30,7 @@ import { registerDocsCommand } from './commands/docs.js' import { registerTokensCommands } from './commands/tokens/index.js' import { registerErrorsCommands } from './commands/errors/index.js' import { registerKvCommands } from './commands/kv/index.js' +import { registerFlagsCommands } from './commands/flags/index.js' import { registerBlobCommands } from './commands/blob/index.js' import { registerDsnCommands } from './commands/dsn/index.js' import { registerScansCommands } from './commands/scans/index.js' @@ -168,6 +169,7 @@ export function createProgram(): Command { registerTokensCommands(program) registerErrorsCommands(program) registerKvCommands(program) +registerFlagsCommands(program) registerBlobCommands(program) registerDsnCommands(program) registerScansCommands(program) diff --git a/apps/temps-cli/src/commands/flags/index.ts b/apps/temps-cli/src/commands/flags/index.ts new file mode 100644 index 000000000..823186792 --- /dev/null +++ b/apps/temps-cli/src/commands/flags/index.ts @@ -0,0 +1,557 @@ +import type { Command } from 'commander' +import { requireAuth } from '../../config/store.js' +import { requireProjectSlug } from '../../config/resolve-project.js' +import { setupClient, client, getErrorMessage } from '../../lib/api-client.js' +import { + listFlags, + createFlag, + getFlag, + updateFlag, + archiveFlag, + setFlagEnvironment, + getProjectBySlug, + getEnvironments, +} from '../../api/sdk.gen.js' +import type { FlagResponse } from '../../api/types.gen.js' +import { withSpinner } from '../../ui/spinner.js' +import { printTable, type TableColumn } from '../../ui/table.js' +import { + newline, + header, + icons, + json, + colors, + success, + info, + keyValue, +} from '../../ui/output.js' + +type FlagValueType = 'bool' | 'string' | 'number' | 'json' + +export function registerFlagsCommands(program: Command): void { + const flags = program + .command('flags') + .alias('flag') + .description('Manage feature flags (runtime config that changes without a redeploy)') + + flags + .command('list') + .alias('ls') + .description('List feature flags') + .option('-p, --project ', 'Project slug or ID') + .option('-e, --environment ', 'Show values for this environment') + .option('--include-archived', 'Include archived flags') + .option('--page ', 'Page number (default: 1)') + .option('--page-size ', 'Items per page (default: 20, max: 100)') + .option('--json', 'Output in JSON format') + .action(listFlagsCmd) + + flags + .command('get ') + .description('Show a feature flag and its per-environment values') + .option('-p, --project ', 'Project slug or ID') + .option('--json', 'Output in JSON format') + .action(getFlagCmd) + + flags + .command('create ') + .description('Create a feature flag') + .option('-p, --project ', 'Project slug or ID') + .requiredOption('-t, --type ', 'Value type: bool, string, number, or json') + .requiredOption('-d, --default ', 'Default value, served when nothing more specific applies') + .option('--description ', 'What this flag controls') + .option( + '--client-visible', + 'Allow this flag to be exposed to browsers (default: server-only)', + ) + .option('--json', 'Output in JSON format') + .action(createFlagCmd) + + flags + .command('update ') + .description('Update a flag definition (default value, description, visibility)') + .option('-p, --project ', 'Project slug or ID') + .option('-d, --default ', 'New default value') + .option('--description ', 'New description') + .option('--client-visible', 'Expose this flag to browsers') + .option('--no-client-visible', 'Make this flag server-only') + .option('--json', 'Output in JSON format') + .action(updateFlagCmd) + + flags + .command('set ') + .description('Set a flag value in one environment') + .option('-p, --project ', 'Project slug or ID') + .requiredOption('-e, --environment ', 'Environment name or slug') + .option('--json', 'Output in JSON format') + .action(setFlagCmd) + + flags + .command('clear ') + .description('Clear a flag override so the environment inherits the default') + .option('-p, --project ', 'Project slug or ID') + .requiredOption('-e, --environment ', 'Environment name or slug') + .action(clearFlagCmd) + + flags + .command('disable ') + .description('Kill switch: serve the default in this environment, ignoring any override') + .option('-p, --project ', 'Project slug or ID') + .requiredOption('-e, --environment ', 'Environment name or slug') + .action((key: string, options: { project?: string; environment: string }) => + toggleFlagCmd(key, options, false), + ) + + flags + .command('enable ') + .description('Re-enable a flag in this environment after a kill switch') + .option('-p, --project ', 'Project slug or ID') + .requiredOption('-e, --environment ', 'Environment name or slug') + .action((key: string, options: { project?: string; environment: string }) => + toggleFlagCmd(key, options, true), + ) + + flags + .command('archive ') + .description('Archive a flag (callers fall back to their own default)') + .option('-p, --project ', 'Project slug or ID') + .action(archiveFlagCmd) +} + +// ============================================================================ +// Helpers +// ============================================================================ + +async function resolveProject(projectOption?: string): Promise<{ slug: string; id: number }> { + const resolved = await requireProjectSlug(projectOption) + if (resolved.source !== 'flag') { + info(`Using project ${colors.bold(resolved.slug)} (from ${resolved.source})`) + } + + const { data, error } = await getProjectBySlug({ client, path: { slug: resolved.slug } }) + if (error || !data) { + throw new Error(`Project "${resolved.slug}" not found`) + } + return { slug: resolved.slug, id: data.id } +} + +async function resolveEnvironmentId(projectId: number, nameOrSlug: string): Promise { + const { data, error } = await getEnvironments({ client, path: { project_id: projectId } }) + if (error || !data) { + throw new Error(getErrorMessage(error)) + } + + const match = data.find((e) => e.name === nameOrSlug || e.slug === nameOrSlug) + if (!match) { + const available = data.map((e) => e.slug).join(', ') + throw new Error(`Environment "${nameOrSlug}" not found. Available: ${available || '(none)'}`) + } + return match.id +} + +/** + * Parse a value typed on the command line into the flag's declared type. + * + * The type comes from the flag itself rather than a CLI option, so `temps flags + * set worker.batch_size 200` sends the number 200, not the string "200" — the + * server rejects a type mismatch, and a shell has no types to offer. + */ +function parseValue(raw: string, valueType: FlagValueType, key: string): unknown { + switch (valueType) { + case 'bool': + if (raw === 'true') return true + if (raw === 'false') return false + throw new Error(`Flag "${key}" is a bool: value must be "true" or "false", got "${raw}"`) + case 'number': { + const n = Number(raw) + if (!Number.isFinite(n)) { + throw new Error(`Flag "${key}" is a number: could not parse "${raw}"`) + } + return n + } + case 'string': + return raw + case 'json': + try { + return JSON.parse(raw) + } catch { + throw new Error(`Flag "${key}" is json: value must be valid JSON, got "${raw}"`) + } + default: + throw new Error(`Unknown value type "${valueType}" for flag "${key}"`) + } +} + +function assertValueType(raw: string): FlagValueType { + if (raw === 'bool' || raw === 'string' || raw === 'number' || raw === 'json') { + return raw + } + throw new Error(`Invalid type "${raw}". Must be one of: bool, string, number, json`) +} + +function formatValue(value: unknown): string { + if (value === null || value === undefined) return colors.dim('(inherits default)') + return typeof value === 'string' ? value : JSON.stringify(value) +} + +/** The value a flag resolves to in one environment, mirroring the evaluator. */ +function effectiveValue(flag: FlagResponse, environmentId: number): string { + const override = flag.environments?.find((e) => e.environment_id === environmentId) + if (!override) return `${formatValue(flag.default_value)} ${colors.dim('(default)')}` + if (!override.enabled) { + return `${formatValue(flag.default_value)} ${colors.warning('(disabled)')}` + } + if (override.value === null || override.value === undefined) { + return `${formatValue(flag.default_value)} ${colors.dim('(default)')}` + } + return formatValue(override.value) +} + +// ============================================================================ +// Commands +// ============================================================================ + +async function listFlagsCmd(options: { + project?: string + environment?: string + includeArchived?: boolean + page?: string + pageSize?: string + json?: boolean +}): Promise { + await requireAuth() + await setupClient() + + const project = await resolveProject(options.project) + + const { data, environmentId } = await withSpinner( + 'Fetching flags...', + async () => { + const environmentId = options.environment + ? await resolveEnvironmentId(project.id, options.environment) + : undefined + + const { data, error } = await listFlags({ + client, + path: { project_id: project.id }, + query: { + include_archived: options.includeArchived ?? false, + ...(options.page ? { page: Number(options.page) } : {}), + ...(options.pageSize ? { page_size: Number(options.pageSize) } : {}), + }, + }) + if (error) throw new Error(getErrorMessage(error)) + return { data, environmentId } + } + ) + + const flags = data?.flags ?? [] + + if (options.json) { + // Emit the whole envelope so scripts can page without guessing. + json(data ?? { flags: [], total: 0, page: 1, page_size: 20, total_pages: 0 }) + return + } + + newline() + const scope = options.environment ? ` in ${options.environment}` : '' + header( + `${icons.folder} Feature flags for ${project.slug}${scope} (${data?.total ?? flags.length})` + ) + + if (flags.length === 0) { + info('No feature flags yet. Create one with: temps flags create --type bool --default false') + newline() + return + } + + const columns: TableColumn[] = [ + { header: 'Key', key: 'key', color: (v) => colors.bold(v) }, + { header: 'Type', key: 'value_type' }, + environmentId !== undefined + ? { header: options.environment!, accessor: (f) => effectiveValue(f, environmentId) } + : { header: 'Default', accessor: (f) => formatValue(f.default_value) }, + { header: 'Client', accessor: (f) => (f.client_visible ? 'yes' : 'no') }, + { header: 'Status', accessor: (f) => (f.archived_at ? colors.dim('archived') : 'active') }, + ] + + printTable(flags, columns, { style: 'minimal' }) + + const total = data?.total ?? flags.length + const totalPages = data?.total_pages ?? 1 + if (total > flags.length) { + info( + `Showing ${flags.length} of ${total} (page ${data?.page ?? 1} of ${totalPages}). Use --page to see more.` + ) + } + newline() +} + +async function getFlagCmd( + key: string, + options: { project?: string; json?: boolean }, +): Promise { + await requireAuth() + await setupClient() + + const project = await resolveProject(options.project) + + const flag = await withSpinner(`Fetching flag ${key}...`, async () => { + const { data, error } = await getFlag({ client, path: { project_id: project.id, key } }) + if (error) throw new Error(getErrorMessage(error)) + if (!data) throw new Error(`Flag "${key}" not found`) + return data + }) + + if (options.json) { + json(flag) + return + } + + newline() + header(`${icons.folder} ${flag.key}`) + keyValue('Type', flag.value_type) + keyValue('Default', formatValue(flag.default_value)) + keyValue('Description', flag.description ?? '-') + keyValue('Client visible', flag.client_visible ? 'yes' : 'no') + if (flag.archived_at) keyValue('Archived', flag.archived_at) + + newline() + if (!flag.environments || flag.environments.length === 0) { + info('No environment overrides — this flag serves its default everywhere.') + } else { + header('Environment overrides') + printTable( + flag.environments, + [ + { header: 'Environment ID', accessor: (e) => String(e.environment_id) }, + { header: 'Enabled', accessor: (e) => (e.enabled ? 'yes' : colors.warning('no (kill switch)')) }, + { header: 'Value', accessor: (e) => formatValue(e.value) }, + ], + { style: 'minimal' }, + ) + } + newline() +} + +async function createFlagCmd( + key: string, + options: { + project?: string + type: string + default: string + description?: string + clientVisible?: boolean + json?: boolean + }, +): Promise { + await requireAuth() + await setupClient() + + const project = await resolveProject(options.project) + const valueType = assertValueType(options.type) + const defaultValue = parseValue(options.default, valueType, key) + + const flag = await withSpinner(`Creating flag ${key}...`, async () => { + const { data, error } = await createFlag({ + client, + path: { project_id: project.id }, + body: { + key, + value_type: valueType, + default_value: defaultValue, + description: options.description, + client_visible: options.clientVisible ?? false, + }, + }) + if (error) throw new Error(getErrorMessage(error)) + if (!data) throw new Error('Flag creation returned no data') + return data + }) + + if (options.json) { + json(flag) + return + } + + newline() + success(`Created flag ${colors.bold(flag.key)} (${flag.value_type}, default ${formatValue(flag.default_value)})`) + if (!flag.client_visible) { + info('Server-only. Pass --client-visible to expose it to browsers.') + } + newline() +} + +async function updateFlagCmd( + key: string, + options: { + project?: string + default?: string + description?: string + clientVisible?: boolean + json?: boolean + }, +): Promise { + await requireAuth() + await setupClient() + + const project = await resolveProject(options.project) + + const flag = await withSpinner(`Updating flag ${key}...`, async () => { + const { data: existing, error: getError } = await getFlag({ + client, + path: { project_id: project.id, key }, + }) + if (getError) throw new Error(getErrorMessage(getError)) + if (!existing) throw new Error(`Flag "${key}" not found`) + + // Only send fields the caller actually passed: an absent field leaves the + // stored value alone, which is not the same as clearing it. + const body: Record = {} + if (options.default !== undefined) { + body.default_value = parseValue(options.default, existing.value_type as FlagValueType, key) + } + if (options.description !== undefined) body.description = options.description + if (options.clientVisible !== undefined) body.client_visible = options.clientVisible + + if (Object.keys(body).length === 0) { + throw new Error('Nothing to update. Pass --default, --description, or --client-visible.') + } + + const { data, error } = await updateFlag({ + client, + path: { project_id: project.id, key }, + body, + }) + if (error) throw new Error(getErrorMessage(error)) + if (!data) throw new Error('Flag update returned no data') + return data + }) + + if (options.json) { + json(flag) + return + } + + newline() + success(`Updated ${colors.bold(flag.key)}`) + newline() +} + +async function setFlagCmd( + key: string, + value: string, + options: { project?: string; environment: string; json?: boolean }, +): Promise { + await requireAuth() + await setupClient() + + const project = await resolveProject(options.project) + + const result = await withSpinner(`Setting ${key} in ${options.environment}...`, async () => { + // Read the flag first so the raw CLI string is parsed into the flag's own + // declared type rather than guessed. + const { data: flag, error: getError } = await getFlag({ + client, + path: { project_id: project.id, key }, + }) + if (getError) throw new Error(getErrorMessage(getError)) + if (!flag) throw new Error(`Flag "${key}" not found`) + + const parsed = parseValue(value, flag.value_type as FlagValueType, key) + const environmentId = await resolveEnvironmentId(project.id, options.environment) + + const { data, error } = await setFlagEnvironment({ + client, + path: { project_id: project.id, key, environment_id: environmentId }, + body: { value: parsed }, + }) + if (error) throw new Error(getErrorMessage(error)) + return data + }) + + if (options.json) { + json(result) + return + } + + newline() + success(`${colors.bold(key)} = ${value} in ${colors.bold(options.environment)}`) + info('Live within seconds — no redeploy needed.') + newline() +} + +async function clearFlagCmd( + key: string, + options: { project?: string; environment: string }, +): Promise { + await requireAuth() + await setupClient() + + const project = await resolveProject(options.project) + + await withSpinner(`Clearing ${key} in ${options.environment}...`, async () => { + const environmentId = await resolveEnvironmentId(project.id, options.environment) + const { error } = await setFlagEnvironment({ + client, + path: { project_id: project.id, key, environment_id: environmentId }, + // Explicit null clears the override; an absent field would leave it alone. + body: { value: null }, + }) + if (error) throw new Error(getErrorMessage(error)) + }) + + newline() + success(`${colors.bold(key)} now inherits its default in ${colors.bold(options.environment)}`) + newline() +} + +async function toggleFlagCmd( + key: string, + options: { project?: string; environment: string }, + enabled: boolean, +): Promise { + await requireAuth() + await setupClient() + + const project = await resolveProject(options.project) + + await withSpinner( + `${enabled ? 'Enabling' : 'Disabling'} ${key} in ${options.environment}...`, + async () => { + const environmentId = await resolveEnvironmentId(project.id, options.environment) + const { error } = await setFlagEnvironment({ + client, + path: { project_id: project.id, key, environment_id: environmentId }, + body: { enabled }, + }) + if (error) throw new Error(getErrorMessage(error)) + }, + ) + + newline() + if (enabled) { + success(`${colors.bold(key)} re-enabled in ${colors.bold(options.environment)}`) + } else { + success(`${colors.bold(key)} disabled in ${colors.bold(options.environment)}`) + info('It now serves its default value, ignoring any override.') + } + newline() +} + +async function archiveFlagCmd(key: string, options: { project?: string }): Promise { + await requireAuth() + await setupClient() + + const project = await resolveProject(options.project) + + await withSpinner(`Archiving ${key}...`, async () => { + const { error } = await archiveFlag({ client, path: { project_id: project.id, key } }) + if (error) throw new Error(getErrorMessage(error)) + }) + + newline() + success(`Archived ${colors.bold(key)}`) + info('Callers now fall back to the default they compiled in.') + newline() +} From abd8014e6db3f1062fee38595fed960053fe01c2 Mon Sep 17 00:00:00 2001 From: David Viejo Date: Mon, 3 Aug 2026 09:32:04 +0200 Subject: [PATCH 05/12] feat(web): add feature flags console UI Lives under the project rather than settings, in the sidebar directly after Environment Variables - the sibling concept it exists to contrast with (env var means redeploy, flag means seconds). The table shows one environment at a time, because the question people arrive with is "what is this flag doing in production?". The detail sheet then shows every environment at once, which is where the project/environment relationship becomes explicit. Kill switch and value are kept visually distinct: the row switch sets the value, the kill switch lives in the row menu and the sheet, and a kill-switched row renders its switch disabled with a Disabled badge. Letting someone toggle a value the kill switch is overriding would be a lie. resolveEffectiveValue() is a third mirror of the evaluator, alongside Rust and the SDK, and is commented as such - if it drifts the console shows one value while the app receives another. Type selection uses radio cards, not a dropdown (four options), and the value control adapts to the flag's type. An unrecognised type renders as text rather than a switch, which would silently mean the wrong thing. --- .../api/client/@tanstack/react-query.gen.ts | 147 +++++- web/src/api/client/index.ts | 4 +- web/src/api/client/sdk.gen.ts | 71 ++- web/src/api/client/types.gen.ts | 453 ++++++++++++++++++ web/src/components/dashboard/Sidebar.tsx | 2 + .../project/flags/CreateFlagDialog.tsx | 253 ++++++++++ .../project/flags/FlagDetailSheet.tsx | 445 +++++++++++++++++ .../project/flags/FlagValueField.tsx | 91 ++++ .../project/flags/ProjectFeatureFlags.tsx | 439 +++++++++++++++++ .../components/project/flags/flag-value.ts | 172 +++++++ web/src/pages/ProjectDetail.tsx | 5 + 11 files changed, 2077 insertions(+), 5 deletions(-) create mode 100644 web/src/components/project/flags/CreateFlagDialog.tsx create mode 100644 web/src/components/project/flags/FlagDetailSheet.tsx create mode 100644 web/src/components/project/flags/FlagValueField.tsx create mode 100644 web/src/components/project/flags/ProjectFeatureFlags.tsx create mode 100644 web/src/components/project/flags/flag-value.ts diff --git a/web/src/api/client/@tanstack/react-query.gen.ts b/web/src/api/client/@tanstack/react-query.gen.ts index e60b601eb..9f3977bd7 100644 --- a/web/src/api/client/@tanstack/react-query.gen.ts +++ b/web/src/api/client/@tanstack/react-query.gen.ts @@ -3,8 +3,8 @@ import { type DefaultError, type InfiniteData, infiniteQueryOptions, queryOptions, type UseMutationOptions } from '@tanstack/react-query'; import { client } from '../client.gen'; -import { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, recordConsoleEvent, recordEventMetrics, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, setDefaultS3Source, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from '../sdk.gen'; -import type { AcknowledgeAlarmData, ActivateAiProviderData, ActivateAiProviderResponse, ActivateApiKeyData, ActivateApiKeyResponse, ActivateConnectionData, ActivateProviderData, AddClusterMemberData, AddClusterMemberResponse, AddContextData, AddEnvironmentDomainData, AddEnvironmentDomainResponse, AddEventsData, AddEventsError, AddEventsResponse2, AddManagedDomainData, AddManagedDomainResponse, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsResponse, AdminDrainNodeData, AdminDrainNodeResponse, AdminDrainStatusData, AdminDrainStatusResponse, AdminGetNodeData, AdminGetNodeResponse, AdminListNodeContainersData, AdminListNodeContainersResponse, AdminListNodesData, AdminListNodesResponse, AdminRemoveNodeData, AdminRemoveNodeResponse, AdminUndrainNodeData, AdminUndrainNodeResponse, ApplyHostnameModeData, ApplyHostnameModeResponse, ArchiveConversationData, ArchiveConversationResponse, AssignRoleData, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesResponse2, BlobCopyData, BlobCopyError, BlobCopyResponse, BlobDeleteData, BlobDeleteError, BlobDeleteResponse, BlobDisableData, BlobDisableResponse, BlobDownloadData, BlobDownloadError, BlobEnableData, BlobEnableResponse, BlobListData, BlobListError, BlobListResponse, BlobPutData, BlobPutError, BlobPutResponse, BlobStatusData, BlobStatusResponse2, BlobUpdateData, BlobUpdateResponse, CancelBackupData, CancelBackupError, CancelBackupResponse2, CancelData, CancelDeploymentData, CancelDeploymentResponse, CancelDomainOrderData, CancelDomainOrderResponse, CancelPgUpgradeData, CancelPgUpgradeResponse, CancelRunData, CancelRunResponse, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunResponse, ChangePasswordSelfData, ChangePasswordSelfResponse, ChangeProjectSourceData, ChangeProjectSourceResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsResponse, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsResponse, CheckCommitExistsData, CheckCommitExistsResponse, CheckDomainStatusData, CheckDomainStatusResponse, CheckExplorerSupportData, CheckExplorerSupportResponse, CheckIpBlockedData, CheckIpBlockedError, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsResponse, ClearPreviewPasswordData, ClearPreviewPasswordResponse, CliDeviceApproveData, CliDeviceApproveResponse2, CliDeviceDenyData, CliDeviceDenyResponse, CliDeviceLookupData, CliDeviceLookupResponse2, CliDevicePollData, CliDevicePollResponse2, CliDeviceStartData, CliDeviceStartResponse2, CliLogoutData, CliLogoutResponse, CmdData, CmdKillData, CmdKillResponse, CmdLogsData, CmdResponse2, ConfirmPendingActionData, ConfirmPendingActionResponse, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryResponse, CreateAgentData, CreateAgentResponse, CreateAlertData, CreateAlertError, CreateAlertResponse, CreateAlertRuleData, CreateAlertRuleResponse, CreateApiKeyData, CreateApiKeyResponse2, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleResponse, CreateBitbucketProviderData, CreateBitbucketProviderResponse, CreateCloudflareProviderData, CreateCloudflareProviderResponse, CreateConversationData, CreateConversationResponse, CreateCustomDomainData, CreateCustomDomainResponse, CreateDashboardData, CreateDashboardError, CreateDashboardResponse, CreateDeploymentTokenData, CreateDeploymentTokenResponse2, CreateDnsProviderData, CreateDnsProviderResponse, CreateDomainData, CreateDomainResponse, CreateDsnData, CreateDsnResponse, CreateEmailDomainData, CreateEmailDomainResponse, CreateEmailProviderData, CreateEmailProviderResponse, CreateEnvironmentData, CreateEnvironmentResponse, CreateEnvironmentVariableData, CreateEnvironmentVariableResponse, CreateFunnelData, CreateFunnelResponse2, CreateGenericProviderData, CreateGenericProviderResponse, CreateGiteaPatProviderData, CreateGiteaPatProviderResponse, CreateGithubPatProviderData, CreateGithubPatProviderResponse, CreateGitlabOauthProviderData, CreateGitlabOauthProviderResponse, CreateGitlabPatProviderData, CreateGitlabPatProviderResponse, CreateGitProviderData, CreateGitProviderResponse, CreateGlobalMcpData, CreateGlobalMcpResponse, CreateGlobalSkillData, CreateGlobalSkillResponse, CreateIncidentData, CreateIncidentResponse, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlResponse, CreateMcpData, CreateMcpResponse, CreateMonitorData, CreateMonitorResponse, CreateNotificationEmailProviderData, CreateNotificationEmailProviderResponse, CreateNotificationProviderData, CreateNotificationProviderResponse, CreateOidcProviderData, CreateOidcProviderResponse, CreateOidcRoleMappingData, CreateOidcRoleMappingResponse, CreateOrRecreateOrderData, CreateOrRecreateOrderResponse, CreatePlanData, CreatePlanResponse2, CreatePrData, CreateProjectData, CreateProjectFromTemplateData, CreateProjectFromTemplateResponse2, CreateProjectReleaseData, CreateProjectReleaseResponse, CreateProjectResponse, CreateProjectSecretData, CreateProjectSecretResponse, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyResponse, CreatePrResponse2, CreateReleaseData, CreateReleaseResponse, CreateRouteData, CreateRouteResponse, CreateS3SourceData, CreateS3SourceError, CreateS3SourceResponse, CreateSandboxData, CreateSandboxResponse, CreateServiceData, CreateServiceResponse, CreateSkillData, CreateSkillResponse, CreateSlackProviderData, CreateSlackProviderResponse, CreateUserData, CreateUserResponse, CreateWebhookData, CreateWebhookProviderData, CreateWebhookProviderResponse, CreateWebhookResponse, DeactivateApiKeyData, DeactivateApiKeyResponse, DeactivateConnectionData, DeactivateProviderData, DeleteAgentData, DeleteAgentResponse, DeleteAlertData, DeleteAlertError, DeleteAlertResponse, DeleteAlertRuleData, DeleteAlertRuleResponse, DeleteApiKeyData, DeleteApiKeyResponse, DeleteBackupData, DeleteBackupError, DeleteBackupResponse, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleResponse, DeleteConnectionData, DeleteConnectionResponse, DeleteCustomDomainData, DeleteCustomDomainResponse, DeleteDashboardData, DeleteDashboardError, DeleteDashboardResponse, DeleteDeploymentTokenData, DeleteDeploymentTokenResponse, DeleteDnsProviderData, DeleteDnsProviderResponse, DeleteDomainData, DeleteDomainResponse, DeleteEmailDomainData, DeleteEmailDomainResponse, DeleteEmailProviderData, DeleteEmailProviderResponse, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainResponse, DeleteEnvironmentResponse, DeleteEnvironmentVariableData, DeleteEnvironmentVariableResponse, DeleteExternalImageData, DeleteExternalImageResponse, DeleteFunnelData, DeleteGitProviderData, DeleteGitProviderResponse, DeleteGlobalMcpData, DeleteGlobalMcpResponse, DeleteGlobalSkillData, DeleteGlobalSkillResponse, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlResponse, DeleteMcpData, DeleteMcpResponse, DeleteMonitorData, DeleteMonitorResponse, DeleteNotificationProviderData, DeleteNotificationProviderResponse, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeletePreferencesData, DeletePreferencesResponse, DeleteProjectData, DeleteProjectResponse, DeleteProjectSecretData, DeleteProjectSecretResponse, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyResponse, DeleteProviderSafelyData, DeleteProviderSafelyResponse, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsResponse, DeleteRouteData, DeleteRouteResponse, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceResponse, DeleteScanData, DeleteScanError, DeleteScanResponse, DeleteSecretData, DeleteSecretResponse, DeleteServiceData, DeleteServiceResponse, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSkillData, DeleteSkillResponse, DeleteSourceMapData, DeleteSourceMapResponse, DeleteStaticBundleData, DeleteStaticBundleResponse, DeleteUserData, DeleteUserResponse, DeleteWebhookData, DeleteWebhookResponse, DeployFromImageData, DeployFromImageResponse, DeployFromImageUploadData, DeployFromImageUploadResponse, DeployFromStaticData, DeployFromStaticResponse, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeResponse, DeploymentMetricsToggleData, DestroySandboxData, DestroySandboxResponse, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceResponse, DetectPublicPresetsData, DetectPublicPresetsResponse, DisableBackupScheduleData, DisableBackupScheduleResponse, DisableMfaData, DisableMfaResponse, DiscoverWorkloadsData, DiscoverWorkloadsResponse, DomainData, DomainResponse2, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveResponse, DownloadObjectData, DownloadObjectResponse, DownloadSkillArchiveData, DownloadSkillArchiveResponse, EmailStatusData, EmailStatusResponse2, EmbeddingsData, EmbeddingsError, EmbeddingsResponse, EnableBackupScheduleData, EnableBackupScheduleResponse, EnrichVisitorData, EnrichVisitorResponse2, ExecData, ExecDetachedData, ExecDetachedResponse2, ExecResponse2, ExecuteDeploymentOperationData, ExecuteDeploymentOperationResponse, ExecuteImportData, ExecuteImportResponse2, ExtendTimeoutData, ExtendTimeoutResponse, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsToggleData, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleResponse, FinalizeOrderData, FinalizeOrderResponse, FinalizeProjectReleaseData, FinalizeProjectReleaseResponse, FindConversationData, FindConversationResponse, GenerateJoinTokenData, GenerateJoinTokenResponse2, GeneratePresetDockerfileData, GeneratePresetDockerfileResponse, GetAccessInfoData, GetAccessInfoResponse, GetActiveVisitorsData, GetActiveVisitorsResponse, GetActivityGraphData, GetActivityGraphResponse, GetAdminGateData, GetAdminGateResponse, GetAgentData, GetAgentResponse, GetAggregatedBucketsData, GetAggregatedBucketsResponse, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownResponse, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesResponse, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineResponse, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownResponse, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownResponse, GetAlertData, GetAlertError, GetAlertResponse, GetAlertRuleData, GetAlertRuleResponse, GetAllRepositoriesByNameData, GetAllRepositoriesByNameResponse, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsResponse, GetAnalyticsEventsCountData, GetAnalyticsEventsCountResponse, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsResponse, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsResponse, GetApiKeyData, GetApiKeyPermissionsData, GetApiKeyPermissionsResponse, GetApiKeyResponse, GetAuditLogData, GetAuditLogResponse, GetBackupData, GetBackupError, GetBackupResponse, GetBackupScheduleData, GetBackupScheduleResponse, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdResponse, GetBucketedIncidentsData, GetBucketedIncidentsResponse, GetBucketedStatusData, GetBucketedStatusResponse, GetChallengeTokenData, GetChallengeTokenResponse, GetCliStatusData, GetClusterHealthData, GetClusterHealthResponse, GetClusterMemberData, GetClusterMemberResponse, GetCmdData, GetCmdResponse, GetContainerDetailData, GetContainerDetailResponse, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableResponse, GetContainerInfoData, GetContainerInfoResponse, GetContainerLogsByIdData, GetContainerLogsData, GetContainerMetricsData, GetContainerMetricsResponse, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailResponse, GetConversationResponse, GetConversationsData, GetConversationsError, GetConversationsResponse, GetCronByIdData, GetCronByIdResponse, GetCronExecutionsData, GetCronExecutionsResponse, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsResponse, GetCurrentMonitorStatusData, GetCurrentMonitorStatusResponse, GetCurrentUserData, GetCurrentUserResponse, GetCustomDomainData, GetCustomDomainResponse, GetDashboardData, GetDashboardError, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsResponse, GetDashboardResponse, GetDeliveryData, GetDeliveryResponse, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentResponse, GetDeploymentData, GetDeploymentJobLogsData, GetDeploymentJobLogsResponse, GetDeploymentJobsData, GetDeploymentJobsResponse, GetDeploymentOperationsData, GetDeploymentOperationsResponse, GetDeploymentOperationStatusData, GetDeploymentOperationStatusResponse, GetDeploymentResponse, GetDeploymentTokenData, GetDeploymentTokenResponse, GetDiskStatusData, GetDiskStatusResponse, GetDnsChangesData, GetDnsChangesResponse, GetDnsProviderData, GetDnsProviderResponse, GetDomainByHostData, GetDomainByHostResponse, GetDomainByIdData, GetDomainByIdResponse, GetDomainByNameData, GetDomainByNameResponse, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsResponse, GetDomainOrderData, GetDomainOrderResponse, GetDomainResponse, GetEmailData, GetEmailEventsData, GetEmailEventsResponse, GetEmailLinksData, GetEmailLinksResponse, GetEmailProviderData, GetEmailProviderResponse, GetEmailResponse, GetEmailStatsData, GetEmailStatsResponse, GetEmailTrackingData, GetEmailTrackingResponse, GetEmailTrackingStatusData, GetEmailTrackingStatusResponse, GetEntityInfoData, GetEntityInfoResponse, GetEnvironmentCronsData, GetEnvironmentCronsResponse, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsResponse, GetEnvironmentResponse, GetEnvironmentsData, GetEnvironmentsResponse, GetEnvironmentVariablesData, GetEnvironmentVariablesResponse, GetEnvironmentVariableValueData, GetEnvironmentVariableValueResponse, GetErrorDashboardStatsData, GetErrorDashboardStatsResponse, GetErrorEventData, GetErrorEventResponse, GetErrorGroupData, GetErrorGroupResponse, GetErrorStatsData, GetErrorStatsResponse, GetErrorTimeSeriesData, GetErrorTimeSeriesResponse, GetEventDetailData, GetEventDetailResponse, GetEventEntriesData, GetEventEntriesResponse, GetEventsCountData, GetEventsCountResponse, GetEventsTimelineData, GetEventsTimelineResponse, GetEventTypeBreakdownData, GetEventTypeBreakdownResponse, GetEventVisitorsData, GetEventVisitorsResponse, GetExternalImageData, GetExternalImageResponse, GetFileData, GetFileResponse, GetFunnelMetricsData, GetFunnelMetricsResponse, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceResponse, GetGeneralStatsData, GetGeneralStatsResponse, GetGitProviderData, GetGitProviderResponse, GetGlobalEventsData, GetGlobalEventsResponse, GetGlobalEventStatsData, GetGlobalEventStatsResponse, GetGlobalMcpData, GetGlobalMcpResponse, GetGlobalSandboxStatusData, GetGlobalSandboxStatusResponse, GetGlobalSkillData, GetGlobalSkillResponse, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsResponse, GetHealthData, GetHealthError, GetHealthResponse, GetHourlyVisitsData, GetHourlyVisitsResponse, GetHttpChallengeDebugData, GetHttpChallengeDebugResponse, GetImportStatusData, GetImportStatusResponse, GetIncidentData, GetIncidentResponse, GetIncidentUpdatesData, GetIncidentUpdatesResponse, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlResponse, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationResponse, GetJoinTokenStatusData, GetJoinTokenStatusResponse, GetLastDeploymentData, GetLastDeploymentResponse, GetLatestScanData, GetLatestScanError, GetLatestScanResponse, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentResponse, GetLiveVisitorsListData, GetLiveVisitorsListResponse, GetLogContextData, GetLogContextError, GetLogContextResponse, GetMcpData, GetMcpResponse, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeResponse, GetMonitorData, GetMonitorResponse, GetNotificationProviderData, GetNotificationProviderResponse, GetOnDemandCertStatusData, GetOnDemandCertStatusResponse, GetOrCreateDsnData, GetOrCreateDsnResponse, GetPageFlowData, GetPageFlowResponse, GetPageHourlySessionsData, GetPageHourlySessionsResponse, GetPagePathDetailData, GetPagePathDetailResponse, GetPagePathsData, GetPagePathsResponse, GetPagePathsSparklinesData, GetPagePathsSparklinesResponse, GetPagePathVisitorsData, GetPagePathVisitorsResponse, GetPendingActionData, GetPendingActionResponse, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsResponse, GetPgUpgradeData, GetPgUpgradeLogsData, GetPgUpgradeLogsResponse, GetPgUpgradeResponse, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsResponse, GetPlatformInfoData, GetPlatformInfoResponse, GetPostgresWalHealthData, GetPostgresWalHealthResponse, GetPreferencesData, GetPreferencesResponse, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPricingData, GetPricingError, GetPricingResponse, GetPrivateIpData, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryResponse, GetProjectBySlugData, GetProjectBySlugResponse, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsResponse, GetProjectResponse, GetProjectsData, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesResponse, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysResponse2, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthResponse, GetProjectsMonitorHealthData, GetProjectsMonitorHealthResponse, GetProjectsResponse, GetProjectStatisticsData, GetProjectStatisticsResponse, GetProjectTemplateData, GetProjectTemplateResponse, GetPropertyBreakdownData, GetPropertyBreakdownResponse, GetPropertyTimelineData, GetPropertyTimelineResponse, GetProviderConnectionsData, GetProviderConnectionsResponse, GetProviderMetadataData, GetProviderMetadataResponse, GetProvidersMetadataData, GetProvidersMetadataResponse, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdResponse, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdResponse, GetProxyLogsData, GetProxyLogsError, GetProxyLogsResponse, GetPublicBranchesData, GetPublicBranchesResponse, GetPublicIpData, GetPublicRepositoryData, GetPublicRepositoryResponse, GetQuotaData, GetQuotaError, GetQuotaResponse, GetRecentActivityData, GetRecentActivityResponse, GetRemoteExternalImageData, GetRemoteExternalImageResponse, GetRepositoryBranchesData, GetRepositoryBranchesResponse, GetRepositoryByIdData, GetRepositoryByIdResponse, GetRepositoryByNameData, GetRepositoryByNameResponse, GetRepositoryPresetByNameData, GetRepositoryPresetByNameResponse, GetRepositoryPresetLiveData, GetRepositoryPresetLiveResponse, GetRepositoryTagsData, GetRepositoryTagsResponse, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesResponse, GetRestoreRunData, GetRestoreRunError, GetRestoreRunResponse, GetRouteData, GetRouteResponse, GetRunData, GetRunResponse, GetRunWithLogsData, GetRunWithLogsResponse, GetS3CredentialsData, GetS3CredentialsResponse, GetS3SourceData, GetS3SourceError, GetS3SourceResponse, GetSandboxData, GetSandboxResponse, GetSandboxStatusData, GetSandboxStatusResponse, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentResponse, GetScanData, GetScanError, GetScanResponse, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesResponse, GetServiceBySlugData, GetServiceBySlugResponse, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesResponse, GetServiceHealthStatusData, GetServiceHealthStatusResponse, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServiceResponse, GetServiceRuntimeData, GetServiceRuntimeResponse, GetServiceStatsData, GetServiceStatsResponse, GetServiceTypeParametersData, GetServiceTypesData, GetServiceTypesResponse, GetSessionDetailsData, GetSessionDetailsResponse, GetSessionEventsData, GetSessionEventsResponse, GetSessionLogsData, GetSessionLogsResponse, GetSessionReplayData, GetSessionReplayError, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsResponse, GetSessionReplayResponse2, GetSettingsData, GetSettingsResponse, GetSkillData, GetSkillResponse, GetSlowQueriesData, GetSlowQueriesResponse, GetStaticBundleData, GetStaticBundleResponse, GetStatusOverviewData, GetStatusOverviewResponse, GetTagsByRepositoryIdData, GetTagsByRepositoryIdResponse, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsResponse, GetTodayStatsData, GetTodayStatsError, GetTodayStatsResponse, GetTraceData, GetTraceError, GetTraceResponse, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceResponse, GetUniqueCountsData, GetUniqueCountsResponse, GetUniqueEventsData, GetUniqueEventsResponse, GetUpdateStatusData, GetUpdateStatusResponse, GetUptimeHistoryData, GetUptimeHistoryResponse, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderResponse, GetUsageRecentData, GetUsageRecentError, GetUsageRecentResponse, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryResponse, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesResponse, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsResponse, GetVisitorByGuidData, GetVisitorByGuidResponse, GetVisitorByIdData, GetVisitorByIdResponse, GetVisitorDetailsData, GetVisitorDetailsResponse, GetVisitorFacetsData, GetVisitorFacetsResponse, GetVisitorInfoData, GetVisitorInfoResponse, GetVisitorJourneyData, GetVisitorJourneyResponse, GetVisitorsData, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsResponse2, GetVisitorsResponse, GetVisitorStatsData, GetVisitorStatsResponse, GetWebhookData, GetWebhookResponse, HandleGitProviderOauthCallbackData, HasAnalyticsEventsData, HasAnalyticsEventsResponse2, HasErrorGroupsData, HasErrorGroupsResponse2, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsResponse, ImportExternalServiceData, ImportExternalServiceResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsData, IngestLogsError, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsData, IngestMetricsError, IngestSentryEnvelopeData, IngestSentryEventData, IngestSentryEventResponse, IngestTracesByPathData, IngestTracesByPathError, IngestTracesData, IngestTracesError, InitSessionReplayData, InitSessionReplayError, InitSessionReplayResponse, JobLogsData, JobStatusData, JobStatusResponse2, KillJobData, KillJobResponse, KvDelData, KvDelResponse, KvDisableData, KvDisableResponse, KvEnableData, KvEnableResponse, KvExpireData, KvExpireResponse, KvGetData, KvGetResponse, KvIncrData, KvIncrResponse, KvKeysData, KvKeysResponse, KvSetData, KvSetResponse, KvStatusData, KvStatusResponse2, KvTtlData, KvTtlResponse, KvUpdateData, KvUpdateResponse, LatestRunForSourceData, LatestRunForSourceResponse, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateResponse, LinkServiceToProjectData, LinkServiceToProjectResponse, ListAgentRunsData, ListAgentRunsResponse, ListAgentsData, ListAgentsResponse2, ListAiProvidersData, ListAiProvidersResponse, ListAlertRulesData, ListAlertRulesResponse, ListAlertsData, ListAlertsError, ListAlertsResponse, ListAllConversationsData, ListAllConversationsResponse, ListAllRunsData, ListAllRunsResponse, ListApiKeysData, ListApiKeysResponse, ListAuditLogsData, ListAuditLogsResponse, ListAvailableContainersData, ListAvailableContainersResponse, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsResponse, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenResponse, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesResponse, ListBackupsForScheduleData, ListBackupsForScheduleResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdResponse, ListConnectionsData, ListConnectionsResponse, ListContainersAtPathData, ListContainersAtPathResponse, ListContainersData, ListContainersResponse, ListConversationsData, ListConversationsResponse, ListCustomDomainsForProjectData, ListCustomDomainsForProjectResponse, ListDashboardsData, ListDashboardsError, ListDashboardsResponse, ListDeliveriesData, ListDeliveriesResponse, ListDeploymentContainerLogsData, ListDeploymentContainerLogsResponse, ListDeploymentTokensData, ListDeploymentTokensResponse, ListDnsProvidersData, ListDnsProvidersResponse, ListDomainsData, ListDomainsResponse2, ListDsnsData, ListDsnsResponse, ListEmailDomainsData, ListEmailDomainsResponse, ListEmailProvidersData, ListEmailProvidersResponse, ListEmailsData, ListEmailsResponse, ListEnrollmentTokensData, ListEnrollmentTokensResponse, ListEntitiesData, ListEntitiesResponse, ListErrorEventsData, ListErrorEventsResponse, ListErrorGroupsData, ListErrorGroupsResponse, ListEventsData, ListEventsResponse, ListEventTypesData, ListEventTypesResponse, ListExternalImagesData, ListExternalImagesResponse, ListExternalPluginsData, ListExternalPluginsResponse, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsResponse, ListFunnelsData, ListFunnelsResponse, ListGitProvidersData, ListGitProvidersResponse, ListGlobalMcpsData, ListGlobalMcpsResponse, ListGlobalSkillsData, ListGlobalSkillsResponse, ListIncidentsData, ListInsightsData, ListInsightsError, ListInsightsResponse, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlResponse, ListJobsData, ListJobsResponse2, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsResponse, ListManagedDomainsData, ListManagedDomainsResponse, ListMcpsData, ListMcpsResponse2, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysResponse, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesResponse, ListMetricNamesData, ListMetricNamesError, ListMetricNamesResponse, ListModelsData, ListModelsError, ListModelsResponse, ListMonitorsData, ListMonitorsResponse, ListNotificationProvidersData, ListNotificationProvidersResponse, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProviderUsersData, ListOidcProviderUsersResponse, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOnDemandCertsData, ListOnDemandCertsResponse2, ListOrdersData, ListOrdersResponse2, ListPeersData, ListPeersResponse, ListPendingActionsData, ListPendingActionsResponse, ListPgUpgradesData, ListPgUpgradesResponse, ListPresetsData, ListPresetsResponse2, ListProjectAlarmsData, ListProjectAlarmsResponse, ListProjectScansData, ListProjectScansError, ListProjectScansResponse, ListProjectSecretsData, ListProjectSecretsResponse, ListProjectServicesData, ListProjectServicesResponse, ListProjectTemplatesData, ListProjectTemplatesResponse, ListProjectTemplateTagsData, ListProjectTemplateTagsResponse, ListProviderKeysData, ListProviderKeysError, ListProviderKeysResponse, ListProviderZonesData, ListProviderZonesResponse, ListPublicProvidersData, ListPublicProvidersResponse, ListReleaseFilesData, ListReleaseFilesResponse, ListReleasesData, ListReleasesResponse, ListRemoteExternalImagesData, ListRemoteExternalImagesResponse, ListRepositoriesByConnectionData, ListRepositoriesByConnectionResponse, ListRepositoriesByProviderData, ListRepositoriesByProviderResponse, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRootContainersData, ListRootContainersResponse, ListRoutesData, ListRoutesResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesResponse, ListSandboxesData, ListSandboxesResponse2, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsResponse, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsResponse, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesResponse, ListSecretsData, ListSecretsResponse2, ListServiceHealthStatusesData, ListServiceHealthStatusesResponse, ListServiceProjectsData, ListServiceProjectsResponse, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesResponse, ListServicesData, ListServicesResponse, ListSkillsData, ListSkillsResponse2, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsResponse, ListSourceFilesData, ListSourceFilesResponse, ListSourceMapsData, ListSourceMapsResponse, ListSourcesData, ListSourcesResponse, ListStaticBundlesData, ListStaticBundlesResponse, ListSyncedRepositoriesData, ListSyncedRepositoriesResponse, ListUsersData, ListUsersResponse, ListWebhooksData, ListWebhooksResponse, LoginData, LoginResponse, LogoutData, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsResponse, MintEnrollmentTokenData, MintEnrollmentTokenResponse2, MkdirData, MkdirResponse, NodeHeartbeatData, NodeHeartbeatResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeResponse, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventResponse, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsResponse, OidcCallbackData, PatchAdminGateData, PatchAdminGateResponse, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PauseDeploymentData, PauseDeploymentResponse, PauseSandboxData, PauseSandboxResponse, PlanRestoreData, PlanRestoreError, PlanRestoreResponse, PostDnsAckData, PostDnsAckResponse, PreviewAlertData, PreviewAlertError, PreviewAlertResponse, PreviewFunnelMetricsData, PreviewFunnelMetricsResponse, PreviewHostnameModeData, PreviewHostnameModeResponse, PromoteClusterMemberData, PromoteDeploymentData, PromoteDeploymentResponse, ProvisionDomainData, ProvisionDomainResponse, PurgeProjectLogsData, PurgeProjectLogsError, PushExternalImageData, PushExternalImageResponse, QueryDataData, QueryDataResponse2, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesResponse, QueryLogsData, QueryLogsError, QueryLogsResponse, QueryMetricsData, QueryMetricsError, QueryMetricsResponse, QueryTracesData, QueryTracesError, QueryTracesResponse, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesResponse, ReadFileData, ReadFileResponse2, ReAnalyzeData, RecordConsoleEventData, RecordEventMetricsData, RecordEventMetricsResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsResponse, RefreshRouteTableData, RefreshRouteTableResponse, RegenerateDsnData, RegenerateDsnResponse, RegisterExternalImageData, RegisterExternalImageResponse, RegisterNodeData, RegisterNodeResponse2, ReinstallGitlabWebhookData, ReinstallGitlabWebhookResponse, RejectPendingActionData, RejectPendingActionResponse, ReloadPluginsData, ReloadPluginsResponse, RemoveClusterMemberData, RemoveClusterMemberResponse, RemoveManagedDomainData, RemoveManagedDomainResponse, RemoveRoleData, RemoveRoleResponse, RenameConversationData, RenameConversationResponse, RenewDomainData, RenewDomainResponse, RequestPasswordResetData, RequestPasswordResetResponse, ResetPasswordData, ResetPasswordResponse, ResizeSandboxData, ResizeSandboxResponse, ResolveAlarmData, RestartContainerData, RestartContainerResponse, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartSandboxData, RestartSandboxResponse, RestoreUserData, RestoreUserResponse, ResumeDeploymentData, ResumeDeploymentResponse, ResumeSandboxData, ResumeSandboxResponse, RetryClusterData, RetryClusterResponse, RetryDeliveryData, RetryDeliveryResponse, RetryPgUpgradeData, RetryPgUpgradeResponse, RetryRunData, RetryRunResponse, RevealGlobalMcpConfigData, RevealGlobalMcpConfigResponse, RevealMcpConfigData, RevealMcpConfigResponse, RevealNotificationProviderConfigData, RevealNotificationProviderConfigResponse, RevealServiceParameterData, RevealServiceParameterResponse, RevenueCreateIntegrationData, RevenueCreateIntegrationResponse, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvResponse, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvResponse, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListProvidersData, RevenueListProvidersResponse, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueUpdateConfigData, RevenueUpdateConfigResponse, RevenueUpdateSecretData, RevenueUpdateSecretResponse, RevokeDsnData, RevokeDsnResponse, RevokeEnrollmentTokenData, RevokeEnrollmentTokenResponse, RevokeJoinTokenData, RevokeJoinTokenResponse, RollbackPgUpgradeData, RollbackPgUpgradeResponse, RollbackToDeploymentData, RollbackToDeploymentResponse, RootfsGcData, RootfsReportData, RotateApiKeyData, RotateApiKeyResponse, RotateDeploymentTokenData, RotateDeploymentTokenResponse, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceResponse, RunConnectionHealthCheckData, RunConnectionHealthCheckResponse, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupResponse, RunScheduleNowData, RunScheduleNowError, RunScheduleNowResponse, SaveAgentTokenData, SaveAgentTokenResponse2, SaveAiProviderCredentialData, SaveAiProviderCredentialResponse, SearchLogsData, SearchLogsError, SearchLogsResponse2, SendEmailData, SendEmailResponse, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceResponse, SetPreviewPasswordData, SetPreviewPasswordResponse2, SetupDnsChallengeData, SetupDnsChallengeResponse2, SetupDnsData, SetupDnsResponse2, SetupEmailTrackingData, SetupEmailTrackingResponse, SetupMfaData, SetupMfaResponse, SleepEnvironmentData, SleepEnvironmentResponse, SmokeTestAgentData, SmokeTestAgentResponse, SourceSandboxData, SourceSandboxResponse, StartAnalysisData, StartAnalysisResponse, StartContainerData, StartContainerResponse, StartFixData, StartGitProviderOauthData, StartOidcLoginBySlugData, StartPgUpgradeData, StartPgUpgradeResponse, StartRestoreData, StartRestoreError, StartRestoreResponse, StartServiceData, StartServiceResponse, StatPathData, StatPathResponse, StopContainerData, StopContainerResponse, StopSandboxData, StopSandboxResponse, StopServiceData, StopServiceResponse, StreamContainerMetricsData, SyncRepositoriesData, SyncRepositoriesResponse, TailDeploymentJobLogsData, TailLogsData, TailLogsError, TeardownDeploymentData, TeardownDeploymentResponse, TeardownEnvironmentData, TeardownEnvironmentResponse, TestNotificationProviderData, TestNotificationProviderResponse, TestOidcProviderData, TestOidcProviderResponse, TestProviderConnectionData, TestProviderConnectionResponse, TestProviderData, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdResponse, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineResponse, TestProviderResponse2, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewResponse, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionResponse, TrackClickData, TrackOpenData, TriggerAgentData, TriggerAgentResponse, TriggerProjectPipelineData, TriggerProjectPipelineResponse, TriggerScanData, TriggerScanError, TriggerScanResponse2, TriggerServiceHealthCheckData, TriggerServiceHealthCheckResponse, TriggerWeeklyDigestData, TriggerWeeklyDigestResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectResponse, UpdateAgentData, UpdateAgentResponse, UpdateAiProviderData, UpdateAiProviderResponse2, UpdateAlertData, UpdateAlertError, UpdateAlertResponse, UpdateAlertRuleData, UpdateAlertRuleResponse, UpdateApiKeyData, UpdateApiKeyResponse, UpdateAutomaticDeployData, UpdateAutomaticDeployResponse, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderResponse, UpdateConnectionTokenData, UpdateConnectionTokenResponse, UpdateCustomDomainData, UpdateCustomDomainResponse, UpdateDashboardData, UpdateDashboardError, UpdateDashboardResponse, UpdateDeploymentTokenData, UpdateDeploymentTokenResponse, UpdateEmailProviderData, UpdateEmailProviderResponse, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentVariableData, UpdateEnvironmentVariableResponse, UpdateErrorGroupData, UpdateFunnelData, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsResponse, UpdateGitSettingsData, UpdateGitSettingsResponse, UpdateGlobalMcpData, UpdateGlobalMcpResponse, UpdateGlobalSkillData, UpdateGlobalSkillResponse, UpdateIncidentStatusData, UpdateIncidentStatusResponse, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlResponse, UpdateManagedDomainData, UpdateManagedDomainResponse, UpdateMcpData, UpdateMcpResponse, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderResponse, UpdateNotificationProviderData, UpdateNotificationProviderResponse, UpdateOidcProviderData, UpdateOidcProviderResponse, UpdatePreferencesData, UpdatePreferencesResponse, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigResponse, UpdateProjectResponse, UpdateProjectSecretData, UpdateProjectSecretResponse, UpdateProjectSettingsData, UpdateProjectSettingsResponse, UpdateProviderData, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyResponse, UpdateProviderResponse, UpdateRouteData, UpdateRouteResponse, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceResponse, UpdateSelfData, UpdateSelfResponse, UpdateServiceData, UpdateServiceResourcesData, UpdateServiceResourcesResponse, UpdateServiceResponse, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationResponse2, UpdateSettingsData, UpdateSettingsResponse, UpdateSkillData, UpdateSkillResponse, UpdateSlackProviderData, UpdateSlackProviderResponse, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsResponse, UpdateUserData, UpdateUserResponse, UpdateWebhookData, UpdateWebhookProviderData, UpdateWebhookProviderResponse, UpdateWebhookResponse, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradeServiceData, UpgradeServiceResponse, UploadGlobalSkillData, UploadGlobalSkillResponse, UploadReleaseFileData, UploadReleaseFileResponse, UploadSkillData, UploadSkillResponse, UploadSourceFileData, UploadSourceFileResponse, UploadSourceMapData, UploadSourceMapResponse, UploadStaticBundleData, UploadStaticBundleResponse, UpsertSecretData, UpsertSecretResponse, ValidateConnectionData, ValidateConnectionResponse, ValidateEmailData, ValidateEmailResponse2, VerifyAndEnableMfaData, VerifyAndEnableMfaResponse, VerifyDomainData, VerifyDomainResponse, VerifyEmailData, VerifyEmailResponse, VerifyManagedDomainData, VerifyManagedDomainResponse, VerifyMfaChallengeData, VerifyMfaChallengeResponse, WakeEnvironmentData, WakeEnvironmentResponse, WebhookTriggerData, WebhookTriggerResponse2, WorkflowDryRunData, WorkflowDryRunResponse, WriteFileData, WriteFileResponse, WriteFilesData, WriteFilesResponse2 } from '../types.gen'; +import { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, recordConsoleEvent, recordEventMetrics, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from '../sdk.gen'; +import type { AcknowledgeAlarmData, ActivateAiProviderData, ActivateAiProviderResponse, ActivateApiKeyData, ActivateApiKeyResponse, ActivateConnectionData, ActivateProviderData, AddClusterMemberData, AddClusterMemberResponse, AddContextData, AddEnvironmentDomainData, AddEnvironmentDomainResponse, AddEventsData, AddEventsError, AddEventsResponse2, AddManagedDomainData, AddManagedDomainResponse, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsResponse, AdminDrainNodeData, AdminDrainNodeResponse, AdminDrainStatusData, AdminDrainStatusResponse, AdminGetNodeData, AdminGetNodeResponse, AdminListNodeContainersData, AdminListNodeContainersResponse, AdminListNodesData, AdminListNodesResponse, AdminRemoveNodeData, AdminRemoveNodeResponse, AdminUndrainNodeData, AdminUndrainNodeResponse, ApplyHostnameModeData, ApplyHostnameModeResponse, ArchiveConversationData, ArchiveConversationResponse, ArchiveFlagData, ArchiveFlagResponse2, AssignRoleData, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesResponse2, BlobCopyData, BlobCopyError, BlobCopyResponse, BlobDeleteData, BlobDeleteError, BlobDeleteResponse, BlobDisableData, BlobDisableResponse, BlobDownloadData, BlobDownloadError, BlobEnableData, BlobEnableResponse, BlobListData, BlobListError, BlobListResponse, BlobPutData, BlobPutError, BlobPutResponse, BlobStatusData, BlobStatusResponse2, BlobUpdateData, BlobUpdateResponse, CancelBackupData, CancelBackupError, CancelBackupResponse2, CancelData, CancelDeploymentData, CancelDeploymentResponse, CancelDomainOrderData, CancelDomainOrderResponse, CancelPgUpgradeData, CancelPgUpgradeResponse, CancelRunData, CancelRunResponse, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunResponse, ChangePasswordSelfData, ChangePasswordSelfResponse, ChangeProjectSourceData, ChangeProjectSourceResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsResponse, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsResponse, CheckCommitExistsData, CheckCommitExistsResponse, CheckDomainStatusData, CheckDomainStatusResponse, CheckExplorerSupportData, CheckExplorerSupportResponse, CheckIpBlockedData, CheckIpBlockedError, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsResponse, ClearPreviewPasswordData, ClearPreviewPasswordResponse, CliDeviceApproveData, CliDeviceApproveResponse2, CliDeviceDenyData, CliDeviceDenyResponse, CliDeviceLookupData, CliDeviceLookupResponse2, CliDevicePollData, CliDevicePollResponse2, CliDeviceStartData, CliDeviceStartResponse2, CliLogoutData, CliLogoutResponse, CmdData, CmdKillData, CmdKillResponse, CmdLogsData, CmdResponse2, ConfirmPendingActionData, ConfirmPendingActionResponse, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryResponse, CreateAgentData, CreateAgentResponse, CreateAlertData, CreateAlertError, CreateAlertResponse, CreateAlertRuleData, CreateAlertRuleResponse, CreateApiKeyData, CreateApiKeyResponse2, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleResponse, CreateBitbucketProviderData, CreateBitbucketProviderResponse, CreateCloudflareProviderData, CreateCloudflareProviderResponse, CreateConversationData, CreateConversationResponse, CreateCustomDomainData, CreateCustomDomainResponse, CreateDashboardData, CreateDashboardError, CreateDashboardResponse, CreateDeploymentTokenData, CreateDeploymentTokenResponse2, CreateDnsProviderData, CreateDnsProviderResponse, CreateDomainData, CreateDomainResponse, CreateDsnData, CreateDsnResponse, CreateEmailDomainData, CreateEmailDomainResponse, CreateEmailProviderData, CreateEmailProviderResponse, CreateEnvironmentData, CreateEnvironmentResponse, CreateEnvironmentVariableData, CreateEnvironmentVariableResponse, CreateFlagData, CreateFlagResponse, CreateFunnelData, CreateFunnelResponse2, CreateGenericProviderData, CreateGenericProviderResponse, CreateGiteaPatProviderData, CreateGiteaPatProviderResponse, CreateGithubPatProviderData, CreateGithubPatProviderResponse, CreateGitlabOauthProviderData, CreateGitlabOauthProviderResponse, CreateGitlabPatProviderData, CreateGitlabPatProviderResponse, CreateGitProviderData, CreateGitProviderResponse, CreateGlobalMcpData, CreateGlobalMcpResponse, CreateGlobalSkillData, CreateGlobalSkillResponse, CreateIncidentData, CreateIncidentResponse, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlResponse, CreateMcpData, CreateMcpResponse, CreateMonitorData, CreateMonitorResponse, CreateNotificationEmailProviderData, CreateNotificationEmailProviderResponse, CreateNotificationProviderData, CreateNotificationProviderResponse, CreateOidcProviderData, CreateOidcProviderResponse, CreateOidcRoleMappingData, CreateOidcRoleMappingResponse, CreateOrRecreateOrderData, CreateOrRecreateOrderResponse, CreatePlanData, CreatePlanResponse2, CreatePrData, CreateProjectData, CreateProjectFromTemplateData, CreateProjectFromTemplateResponse2, CreateProjectReleaseData, CreateProjectReleaseResponse, CreateProjectResponse, CreateProjectSecretData, CreateProjectSecretResponse, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyResponse, CreatePrResponse2, CreateReleaseData, CreateReleaseResponse, CreateRouteData, CreateRouteResponse, CreateS3SourceData, CreateS3SourceError, CreateS3SourceResponse, CreateSandboxData, CreateSandboxResponse, CreateServiceData, CreateServiceResponse, CreateSkillData, CreateSkillResponse, CreateSlackProviderData, CreateSlackProviderResponse, CreateUserData, CreateUserResponse, CreateWebhookData, CreateWebhookProviderData, CreateWebhookProviderResponse, CreateWebhookResponse, DeactivateApiKeyData, DeactivateApiKeyResponse, DeactivateConnectionData, DeactivateProviderData, DeleteAgentData, DeleteAgentResponse, DeleteAlertData, DeleteAlertError, DeleteAlertResponse, DeleteAlertRuleData, DeleteAlertRuleResponse, DeleteApiKeyData, DeleteApiKeyResponse, DeleteBackupData, DeleteBackupError, DeleteBackupResponse, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleResponse, DeleteConnectionData, DeleteConnectionResponse, DeleteCustomDomainData, DeleteCustomDomainResponse, DeleteDashboardData, DeleteDashboardError, DeleteDashboardResponse, DeleteDeploymentTokenData, DeleteDeploymentTokenResponse, DeleteDnsProviderData, DeleteDnsProviderResponse, DeleteDomainData, DeleteDomainResponse, DeleteEmailDomainData, DeleteEmailDomainResponse, DeleteEmailProviderData, DeleteEmailProviderResponse, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainResponse, DeleteEnvironmentResponse, DeleteEnvironmentVariableData, DeleteEnvironmentVariableResponse, DeleteExternalImageData, DeleteExternalImageResponse, DeleteFunnelData, DeleteGitProviderData, DeleteGitProviderResponse, DeleteGlobalMcpData, DeleteGlobalMcpResponse, DeleteGlobalSkillData, DeleteGlobalSkillResponse, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlResponse, DeleteMcpData, DeleteMcpResponse, DeleteMonitorData, DeleteMonitorResponse, DeleteNotificationProviderData, DeleteNotificationProviderResponse, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeletePreferencesData, DeletePreferencesResponse, DeleteProjectData, DeleteProjectResponse, DeleteProjectSecretData, DeleteProjectSecretResponse, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyResponse, DeleteProviderSafelyData, DeleteProviderSafelyResponse, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsResponse, DeleteRouteData, DeleteRouteResponse, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceResponse, DeleteScanData, DeleteScanError, DeleteScanResponse, DeleteSecretData, DeleteSecretResponse, DeleteServiceData, DeleteServiceResponse, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSkillData, DeleteSkillResponse, DeleteSourceMapData, DeleteSourceMapResponse, DeleteStaticBundleData, DeleteStaticBundleResponse, DeleteUserData, DeleteUserResponse, DeleteWebhookData, DeleteWebhookResponse, DeployFromImageData, DeployFromImageResponse, DeployFromImageUploadData, DeployFromImageUploadResponse, DeployFromStaticData, DeployFromStaticResponse, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeResponse, DeploymentMetricsToggleData, DestroySandboxData, DestroySandboxResponse, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceResponse, DetectPublicPresetsData, DetectPublicPresetsResponse, DisableBackupScheduleData, DisableBackupScheduleResponse, DisableMfaData, DisableMfaResponse, DiscoverWorkloadsData, DiscoverWorkloadsResponse, DomainData, DomainResponse2, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveResponse, DownloadObjectData, DownloadObjectResponse, DownloadSkillArchiveData, DownloadSkillArchiveResponse, EmailStatusData, EmailStatusResponse2, EmbeddingsData, EmbeddingsError, EmbeddingsResponse, EnableBackupScheduleData, EnableBackupScheduleResponse, EnrichVisitorData, EnrichVisitorResponse2, ExecData, ExecDetachedData, ExecDetachedResponse2, ExecResponse2, ExecuteDeploymentOperationData, ExecuteDeploymentOperationResponse, ExecuteImportData, ExecuteImportResponse2, ExtendTimeoutData, ExtendTimeoutResponse, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsToggleData, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleResponse, FinalizeOrderData, FinalizeOrderResponse, FinalizeProjectReleaseData, FinalizeProjectReleaseResponse, FindConversationData, FindConversationResponse, GenerateJoinTokenData, GenerateJoinTokenResponse2, GeneratePresetDockerfileData, GeneratePresetDockerfileResponse, GetAccessInfoData, GetAccessInfoResponse, GetActiveVisitorsData, GetActiveVisitorsResponse, GetActivityGraphData, GetActivityGraphResponse, GetAdminGateData, GetAdminGateResponse, GetAgentData, GetAgentResponse, GetAggregatedBucketsData, GetAggregatedBucketsResponse, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownResponse, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesResponse, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineResponse, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownResponse, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownResponse, GetAlertData, GetAlertError, GetAlertResponse, GetAlertRuleData, GetAlertRuleResponse, GetAllRepositoriesByNameData, GetAllRepositoriesByNameResponse, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsResponse, GetAnalyticsEventsCountData, GetAnalyticsEventsCountResponse, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsResponse, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsResponse, GetApiKeyData, GetApiKeyPermissionsData, GetApiKeyPermissionsResponse, GetApiKeyResponse, GetAuditLogData, GetAuditLogResponse, GetBackupData, GetBackupError, GetBackupResponse, GetBackupScheduleData, GetBackupScheduleResponse, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdResponse, GetBucketedIncidentsData, GetBucketedIncidentsResponse, GetBucketedStatusData, GetBucketedStatusResponse, GetChallengeTokenData, GetChallengeTokenResponse, GetCliStatusData, GetClusterHealthData, GetClusterHealthResponse, GetClusterMemberData, GetClusterMemberResponse, GetCmdData, GetCmdResponse, GetContainerDetailData, GetContainerDetailResponse, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableResponse, GetContainerInfoData, GetContainerInfoResponse, GetContainerLogsByIdData, GetContainerLogsData, GetContainerMetricsData, GetContainerMetricsResponse, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailResponse, GetConversationResponse, GetConversationsData, GetConversationsError, GetConversationsResponse, GetCronByIdData, GetCronByIdResponse, GetCronExecutionsData, GetCronExecutionsResponse, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsResponse, GetCurrentMonitorStatusData, GetCurrentMonitorStatusResponse, GetCurrentUserData, GetCurrentUserResponse, GetCustomDomainData, GetCustomDomainResponse, GetDashboardData, GetDashboardError, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsResponse, GetDashboardResponse, GetDeliveryData, GetDeliveryResponse, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentResponse, GetDeploymentData, GetDeploymentJobLogsData, GetDeploymentJobLogsResponse, GetDeploymentJobsData, GetDeploymentJobsResponse, GetDeploymentOperationsData, GetDeploymentOperationsResponse, GetDeploymentOperationStatusData, GetDeploymentOperationStatusResponse, GetDeploymentResponse, GetDeploymentTokenData, GetDeploymentTokenResponse, GetDiskStatusData, GetDiskStatusResponse, GetDnsChangesData, GetDnsChangesResponse, GetDnsProviderData, GetDnsProviderResponse, GetDomainByHostData, GetDomainByHostResponse, GetDomainByIdData, GetDomainByIdResponse, GetDomainByNameData, GetDomainByNameResponse, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsResponse, GetDomainOrderData, GetDomainOrderResponse, GetDomainResponse, GetEmailData, GetEmailEventsData, GetEmailEventsResponse, GetEmailLinksData, GetEmailLinksResponse, GetEmailProviderData, GetEmailProviderResponse, GetEmailResponse, GetEmailStatsData, GetEmailStatsResponse, GetEmailTrackingData, GetEmailTrackingResponse, GetEmailTrackingStatusData, GetEmailTrackingStatusResponse, GetEntityInfoData, GetEntityInfoResponse, GetEnvironmentCronsData, GetEnvironmentCronsResponse, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsResponse, GetEnvironmentResponse, GetEnvironmentsData, GetEnvironmentsResponse, GetEnvironmentVariablesData, GetEnvironmentVariablesResponse, GetEnvironmentVariableValueData, GetEnvironmentVariableValueResponse, GetErrorDashboardStatsData, GetErrorDashboardStatsResponse, GetErrorEventData, GetErrorEventResponse, GetErrorGroupData, GetErrorGroupResponse, GetErrorStatsData, GetErrorStatsResponse, GetErrorTimeSeriesData, GetErrorTimeSeriesResponse, GetEventDetailData, GetEventDetailResponse, GetEventEntriesData, GetEventEntriesResponse, GetEventsCountData, GetEventsCountResponse, GetEventsTimelineData, GetEventsTimelineResponse, GetEventTypeBreakdownData, GetEventTypeBreakdownResponse, GetEventVisitorsData, GetEventVisitorsResponse, GetExternalImageData, GetExternalImageResponse, GetFileData, GetFileResponse, GetFlagData, GetFlagResponse, GetFlagSnapshotData, GetFlagSnapshotResponse, GetFunnelMetricsData, GetFunnelMetricsResponse, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceResponse, GetGeneralStatsData, GetGeneralStatsResponse, GetGitProviderData, GetGitProviderResponse, GetGlobalEventsData, GetGlobalEventsResponse, GetGlobalEventStatsData, GetGlobalEventStatsResponse, GetGlobalMcpData, GetGlobalMcpResponse, GetGlobalSandboxStatusData, GetGlobalSandboxStatusResponse, GetGlobalSkillData, GetGlobalSkillResponse, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsResponse, GetHealthData, GetHealthError, GetHealthResponse, GetHourlyVisitsData, GetHourlyVisitsResponse, GetHttpChallengeDebugData, GetHttpChallengeDebugResponse, GetImportStatusData, GetImportStatusResponse, GetIncidentData, GetIncidentResponse, GetIncidentUpdatesData, GetIncidentUpdatesResponse, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlResponse, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationResponse, GetJoinTokenStatusData, GetJoinTokenStatusResponse, GetLastDeploymentData, GetLastDeploymentResponse, GetLatestScanData, GetLatestScanError, GetLatestScanResponse, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentResponse, GetLiveVisitorsListData, GetLiveVisitorsListResponse, GetLogContextData, GetLogContextError, GetLogContextResponse, GetMcpData, GetMcpResponse, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeResponse, GetMonitorData, GetMonitorResponse, GetNotificationProviderData, GetNotificationProviderResponse, GetOnDemandCertStatusData, GetOnDemandCertStatusResponse, GetOrCreateDsnData, GetOrCreateDsnResponse, GetPageFlowData, GetPageFlowResponse, GetPageHourlySessionsData, GetPageHourlySessionsResponse, GetPagePathDetailData, GetPagePathDetailResponse, GetPagePathsData, GetPagePathsResponse, GetPagePathsSparklinesData, GetPagePathsSparklinesResponse, GetPagePathVisitorsData, GetPagePathVisitorsResponse, GetPendingActionData, GetPendingActionResponse, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsResponse, GetPgUpgradeData, GetPgUpgradeLogsData, GetPgUpgradeLogsResponse, GetPgUpgradeResponse, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsResponse, GetPlatformInfoData, GetPlatformInfoResponse, GetPostgresWalHealthData, GetPostgresWalHealthResponse, GetPreferencesData, GetPreferencesResponse, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPricingData, GetPricingError, GetPricingResponse, GetPrivateIpData, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryResponse, GetProjectBySlugData, GetProjectBySlugResponse, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsResponse, GetProjectResponse, GetProjectsData, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesResponse, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysResponse2, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthResponse, GetProjectsMonitorHealthData, GetProjectsMonitorHealthResponse, GetProjectsResponse, GetProjectStatisticsData, GetProjectStatisticsResponse, GetProjectTemplateData, GetProjectTemplateResponse, GetPropertyBreakdownData, GetPropertyBreakdownResponse, GetPropertyTimelineData, GetPropertyTimelineResponse, GetProviderConnectionsData, GetProviderConnectionsResponse, GetProviderMetadataData, GetProviderMetadataResponse, GetProvidersMetadataData, GetProvidersMetadataResponse, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdResponse, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdResponse, GetProxyLogsData, GetProxyLogsError, GetProxyLogsResponse, GetPublicBranchesData, GetPublicBranchesResponse, GetPublicIpData, GetPublicRepositoryData, GetPublicRepositoryResponse, GetQuotaData, GetQuotaError, GetQuotaResponse, GetRecentActivityData, GetRecentActivityResponse, GetRemoteExternalImageData, GetRemoteExternalImageResponse, GetRepositoryBranchesData, GetRepositoryBranchesResponse, GetRepositoryByIdData, GetRepositoryByIdResponse, GetRepositoryByNameData, GetRepositoryByNameResponse, GetRepositoryPresetByNameData, GetRepositoryPresetByNameResponse, GetRepositoryPresetLiveData, GetRepositoryPresetLiveResponse, GetRepositoryTagsData, GetRepositoryTagsResponse, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesResponse, GetRestoreRunData, GetRestoreRunError, GetRestoreRunResponse, GetRouteData, GetRouteResponse, GetRunData, GetRunResponse, GetRunWithLogsData, GetRunWithLogsResponse, GetS3CredentialsData, GetS3CredentialsResponse, GetS3SourceData, GetS3SourceError, GetS3SourceResponse, GetSandboxData, GetSandboxResponse, GetSandboxStatusData, GetSandboxStatusResponse, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentResponse, GetScanData, GetScanError, GetScanResponse, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesResponse, GetServiceBySlugData, GetServiceBySlugResponse, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesResponse, GetServiceHealthStatusData, GetServiceHealthStatusResponse, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServiceResponse, GetServiceRuntimeData, GetServiceRuntimeResponse, GetServiceStatsData, GetServiceStatsResponse, GetServiceTypeParametersData, GetServiceTypesData, GetServiceTypesResponse, GetSessionDetailsData, GetSessionDetailsResponse, GetSessionEventsData, GetSessionEventsResponse, GetSessionLogsData, GetSessionLogsResponse, GetSessionReplayData, GetSessionReplayError, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsResponse, GetSessionReplayResponse2, GetSettingsData, GetSettingsResponse, GetSkillData, GetSkillResponse, GetSlowQueriesData, GetSlowQueriesResponse, GetStaticBundleData, GetStaticBundleResponse, GetStatusOverviewData, GetStatusOverviewResponse, GetTagsByRepositoryIdData, GetTagsByRepositoryIdResponse, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsResponse, GetTodayStatsData, GetTodayStatsError, GetTodayStatsResponse, GetTraceData, GetTraceError, GetTraceResponse, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceResponse, GetUniqueCountsData, GetUniqueCountsResponse, GetUniqueEventsData, GetUniqueEventsResponse, GetUpdateStatusData, GetUpdateStatusResponse, GetUptimeHistoryData, GetUptimeHistoryResponse, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderResponse, GetUsageRecentData, GetUsageRecentError, GetUsageRecentResponse, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryResponse, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesResponse, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsResponse, GetVisitorByGuidData, GetVisitorByGuidResponse, GetVisitorByIdData, GetVisitorByIdResponse, GetVisitorDetailsData, GetVisitorDetailsResponse, GetVisitorFacetsData, GetVisitorFacetsResponse, GetVisitorInfoData, GetVisitorInfoResponse, GetVisitorJourneyData, GetVisitorJourneyResponse, GetVisitorsData, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsResponse2, GetVisitorsResponse, GetVisitorStatsData, GetVisitorStatsResponse, GetWebhookData, GetWebhookResponse, HandleGitProviderOauthCallbackData, HasAnalyticsEventsData, HasAnalyticsEventsResponse2, HasErrorGroupsData, HasErrorGroupsResponse2, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsResponse, ImportExternalServiceData, ImportExternalServiceResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsData, IngestLogsError, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsData, IngestMetricsError, IngestSentryEnvelopeData, IngestSentryEventData, IngestSentryEventResponse, IngestTracesByPathData, IngestTracesByPathError, IngestTracesData, IngestTracesError, InitSessionReplayData, InitSessionReplayError, InitSessionReplayResponse, JobLogsData, JobStatusData, JobStatusResponse2, KillJobData, KillJobResponse, KvDelData, KvDelResponse, KvDisableData, KvDisableResponse, KvEnableData, KvEnableResponse, KvExpireData, KvExpireResponse, KvGetData, KvGetResponse, KvIncrData, KvIncrResponse, KvKeysData, KvKeysResponse, KvSetData, KvSetResponse, KvStatusData, KvStatusResponse2, KvTtlData, KvTtlResponse, KvUpdateData, KvUpdateResponse, LatestRunForSourceData, LatestRunForSourceResponse, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateResponse, LinkServiceToProjectData, LinkServiceToProjectResponse, ListAgentRunsData, ListAgentRunsResponse, ListAgentsData, ListAgentsResponse2, ListAiProvidersData, ListAiProvidersResponse, ListAlertRulesData, ListAlertRulesResponse, ListAlertsData, ListAlertsError, ListAlertsResponse, ListAllConversationsData, ListAllConversationsResponse, ListAllRunsData, ListAllRunsResponse, ListApiKeysData, ListApiKeysResponse, ListAuditLogsData, ListAuditLogsResponse, ListAvailableContainersData, ListAvailableContainersResponse, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsResponse, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenResponse, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesResponse, ListBackupsForScheduleData, ListBackupsForScheduleResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdResponse, ListConnectionsData, ListConnectionsResponse, ListContainersAtPathData, ListContainersAtPathResponse, ListContainersData, ListContainersResponse, ListConversationsData, ListConversationsResponse, ListCustomDomainsForProjectData, ListCustomDomainsForProjectResponse, ListDashboardsData, ListDashboardsError, ListDashboardsResponse, ListDeliveriesData, ListDeliveriesResponse, ListDeploymentContainerLogsData, ListDeploymentContainerLogsResponse, ListDeploymentTokensData, ListDeploymentTokensResponse, ListDnsProvidersData, ListDnsProvidersResponse, ListDomainsData, ListDomainsResponse2, ListDsnsData, ListDsnsResponse, ListEmailDomainsData, ListEmailDomainsResponse, ListEmailProvidersData, ListEmailProvidersResponse, ListEmailsData, ListEmailsResponse, ListEnrollmentTokensData, ListEnrollmentTokensResponse, ListEntitiesData, ListEntitiesResponse, ListErrorEventsData, ListErrorEventsResponse, ListErrorGroupsData, ListErrorGroupsResponse, ListEventsData, ListEventsResponse, ListEventTypesData, ListEventTypesResponse, ListExternalImagesData, ListExternalImagesResponse, ListExternalPluginsData, ListExternalPluginsResponse, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsResponse, ListFlagsData, ListFlagsResponse, ListFunnelsData, ListFunnelsResponse, ListGitProvidersData, ListGitProvidersResponse, ListGlobalMcpsData, ListGlobalMcpsResponse, ListGlobalSkillsData, ListGlobalSkillsResponse, ListIncidentsData, ListInsightsData, ListInsightsError, ListInsightsResponse, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlResponse, ListJobsData, ListJobsResponse2, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsResponse, ListManagedDomainsData, ListManagedDomainsResponse, ListMcpsData, ListMcpsResponse2, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysResponse, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesResponse, ListMetricNamesData, ListMetricNamesError, ListMetricNamesResponse, ListModelsData, ListModelsError, ListModelsResponse, ListMonitorsData, ListMonitorsResponse, ListNotificationProvidersData, ListNotificationProvidersResponse, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProviderUsersData, ListOidcProviderUsersResponse, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOnDemandCertsData, ListOnDemandCertsResponse2, ListOrdersData, ListOrdersResponse2, ListPeersData, ListPeersResponse, ListPendingActionsData, ListPendingActionsResponse, ListPgUpgradesData, ListPgUpgradesResponse, ListPresetsData, ListPresetsResponse2, ListProjectAlarmsData, ListProjectAlarmsResponse, ListProjectScansData, ListProjectScansError, ListProjectScansResponse, ListProjectSecretsData, ListProjectSecretsResponse, ListProjectServicesData, ListProjectServicesResponse, ListProjectTemplatesData, ListProjectTemplatesResponse, ListProjectTemplateTagsData, ListProjectTemplateTagsResponse, ListProviderKeysData, ListProviderKeysError, ListProviderKeysResponse, ListProviderZonesData, ListProviderZonesResponse, ListPublicProvidersData, ListPublicProvidersResponse, ListReleaseFilesData, ListReleaseFilesResponse, ListReleasesData, ListReleasesResponse, ListRemoteExternalImagesData, ListRemoteExternalImagesResponse, ListRepositoriesByConnectionData, ListRepositoriesByConnectionResponse, ListRepositoriesByProviderData, ListRepositoriesByProviderResponse, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRootContainersData, ListRootContainersResponse, ListRoutesData, ListRoutesResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesResponse, ListSandboxesData, ListSandboxesResponse2, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsResponse, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsResponse, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesResponse, ListSecretsData, ListSecretsResponse2, ListServiceHealthStatusesData, ListServiceHealthStatusesResponse, ListServiceProjectsData, ListServiceProjectsResponse, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesResponse, ListServicesData, ListServicesResponse, ListSkillsData, ListSkillsResponse2, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsResponse, ListSourceFilesData, ListSourceFilesResponse, ListSourceMapsData, ListSourceMapsResponse, ListSourcesData, ListSourcesResponse, ListStaticBundlesData, ListStaticBundlesResponse, ListSyncedRepositoriesData, ListSyncedRepositoriesResponse, ListUsersData, ListUsersResponse, ListWebhooksData, ListWebhooksResponse, LoginData, LoginResponse, LogoutData, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsResponse, MintEnrollmentTokenData, MintEnrollmentTokenResponse2, MkdirData, MkdirResponse, NodeHeartbeatData, NodeHeartbeatResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeResponse, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventResponse, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsResponse, OidcCallbackData, PatchAdminGateData, PatchAdminGateResponse, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PauseDeploymentData, PauseDeploymentResponse, PauseSandboxData, PauseSandboxResponse, PlanRestoreData, PlanRestoreError, PlanRestoreResponse, PostDnsAckData, PostDnsAckResponse, PreviewAlertData, PreviewAlertError, PreviewAlertResponse, PreviewFunnelMetricsData, PreviewFunnelMetricsResponse, PreviewHostnameModeData, PreviewHostnameModeResponse, PromoteClusterMemberData, PromoteDeploymentData, PromoteDeploymentResponse, ProvisionDomainData, ProvisionDomainResponse, PurgeProjectLogsData, PurgeProjectLogsError, PushExternalImageData, PushExternalImageResponse, QueryDataData, QueryDataResponse2, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesResponse, QueryLogsData, QueryLogsError, QueryLogsResponse, QueryMetricsData, QueryMetricsError, QueryMetricsResponse, QueryTracesData, QueryTracesError, QueryTracesResponse, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesResponse, ReadFileData, ReadFileResponse2, ReAnalyzeData, RecordConsoleEventData, RecordEventMetricsData, RecordEventMetricsResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsResponse, RefreshRouteTableData, RefreshRouteTableResponse, RegenerateDsnData, RegenerateDsnResponse, RegisterExternalImageData, RegisterExternalImageResponse, RegisterNodeData, RegisterNodeResponse2, ReinstallGitlabWebhookData, ReinstallGitlabWebhookResponse, RejectPendingActionData, RejectPendingActionResponse, ReloadPluginsData, ReloadPluginsResponse, RemoveClusterMemberData, RemoveClusterMemberResponse, RemoveManagedDomainData, RemoveManagedDomainResponse, RemoveRoleData, RemoveRoleResponse, RenameConversationData, RenameConversationResponse, RenewDomainData, RenewDomainResponse, RequestPasswordResetData, RequestPasswordResetResponse, ResetPasswordData, ResetPasswordResponse, ResizeSandboxData, ResizeSandboxResponse, ResolveAlarmData, RestartContainerData, RestartContainerResponse, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartSandboxData, RestartSandboxResponse, RestoreUserData, RestoreUserResponse, ResumeDeploymentData, ResumeDeploymentResponse, ResumeSandboxData, ResumeSandboxResponse, RetryClusterData, RetryClusterResponse, RetryDeliveryData, RetryDeliveryResponse, RetryPgUpgradeData, RetryPgUpgradeResponse, RetryRunData, RetryRunResponse, RevealGlobalMcpConfigData, RevealGlobalMcpConfigResponse, RevealMcpConfigData, RevealMcpConfigResponse, RevealNotificationProviderConfigData, RevealNotificationProviderConfigResponse, RevealServiceParameterData, RevealServiceParameterResponse, RevenueCreateIntegrationData, RevenueCreateIntegrationResponse, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvResponse, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvResponse, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListProvidersData, RevenueListProvidersResponse, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueUpdateConfigData, RevenueUpdateConfigResponse, RevenueUpdateSecretData, RevenueUpdateSecretResponse, RevokeDsnData, RevokeDsnResponse, RevokeEnrollmentTokenData, RevokeEnrollmentTokenResponse, RevokeJoinTokenData, RevokeJoinTokenResponse, RollbackPgUpgradeData, RollbackPgUpgradeResponse, RollbackToDeploymentData, RollbackToDeploymentResponse, RootfsGcData, RootfsReportData, RotateApiKeyData, RotateApiKeyResponse, RotateDeploymentTokenData, RotateDeploymentTokenResponse, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceResponse, RunConnectionHealthCheckData, RunConnectionHealthCheckResponse, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupResponse, RunScheduleNowData, RunScheduleNowError, RunScheduleNowResponse, SaveAgentTokenData, SaveAgentTokenResponse2, SaveAiProviderCredentialData, SaveAiProviderCredentialResponse, SearchLogsData, SearchLogsError, SearchLogsResponse2, SendEmailData, SendEmailResponse, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceResponse, SetFlagEnvironmentData, SetFlagEnvironmentResponse, SetPreviewPasswordData, SetPreviewPasswordResponse2, SetupDnsChallengeData, SetupDnsChallengeResponse2, SetupDnsData, SetupDnsResponse2, SetupEmailTrackingData, SetupEmailTrackingResponse, SetupMfaData, SetupMfaResponse, SleepEnvironmentData, SleepEnvironmentResponse, SmokeTestAgentData, SmokeTestAgentResponse, SourceSandboxData, SourceSandboxResponse, StartAnalysisData, StartAnalysisResponse, StartContainerData, StartContainerResponse, StartFixData, StartGitProviderOauthData, StartOidcLoginBySlugData, StartPgUpgradeData, StartPgUpgradeResponse, StartRestoreData, StartRestoreError, StartRestoreResponse, StartServiceData, StartServiceResponse, StatPathData, StatPathResponse, StopContainerData, StopContainerResponse, StopSandboxData, StopSandboxResponse, StopServiceData, StopServiceResponse, StreamContainerMetricsData, SyncRepositoriesData, SyncRepositoriesResponse, TailDeploymentJobLogsData, TailLogsData, TailLogsError, TeardownDeploymentData, TeardownDeploymentResponse, TeardownEnvironmentData, TeardownEnvironmentResponse, TestNotificationProviderData, TestNotificationProviderResponse, TestOidcProviderData, TestOidcProviderResponse, TestProviderConnectionData, TestProviderConnectionResponse, TestProviderData, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdResponse, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineResponse, TestProviderResponse2, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewResponse, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionResponse, TrackClickData, TrackOpenData, TriggerAgentData, TriggerAgentResponse, TriggerProjectPipelineData, TriggerProjectPipelineResponse, TriggerScanData, TriggerScanError, TriggerScanResponse2, TriggerServiceHealthCheckData, TriggerServiceHealthCheckResponse, TriggerWeeklyDigestData, TriggerWeeklyDigestResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectResponse, UpdateAgentData, UpdateAgentResponse, UpdateAiProviderData, UpdateAiProviderResponse2, UpdateAlertData, UpdateAlertError, UpdateAlertResponse, UpdateAlertRuleData, UpdateAlertRuleResponse, UpdateApiKeyData, UpdateApiKeyResponse, UpdateAutomaticDeployData, UpdateAutomaticDeployResponse, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderResponse, UpdateConnectionTokenData, UpdateConnectionTokenResponse, UpdateCustomDomainData, UpdateCustomDomainResponse, UpdateDashboardData, UpdateDashboardError, UpdateDashboardResponse, UpdateDeploymentTokenData, UpdateDeploymentTokenResponse, UpdateEmailProviderData, UpdateEmailProviderResponse, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentVariableData, UpdateEnvironmentVariableResponse, UpdateErrorGroupData, UpdateFlagData, UpdateFlagResponse, UpdateFunnelData, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsResponse, UpdateGitSettingsData, UpdateGitSettingsResponse, UpdateGlobalMcpData, UpdateGlobalMcpResponse, UpdateGlobalSkillData, UpdateGlobalSkillResponse, UpdateIncidentStatusData, UpdateIncidentStatusResponse, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlResponse, UpdateManagedDomainData, UpdateManagedDomainResponse, UpdateMcpData, UpdateMcpResponse, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderResponse, UpdateNotificationProviderData, UpdateNotificationProviderResponse, UpdateOidcProviderData, UpdateOidcProviderResponse, UpdatePreferencesData, UpdatePreferencesResponse, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigResponse, UpdateProjectResponse, UpdateProjectSecretData, UpdateProjectSecretResponse, UpdateProjectSettingsData, UpdateProjectSettingsResponse, UpdateProviderData, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyResponse, UpdateProviderResponse, UpdateRouteData, UpdateRouteResponse, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceResponse, UpdateSelfData, UpdateSelfResponse, UpdateServiceData, UpdateServiceResourcesData, UpdateServiceResourcesResponse, UpdateServiceResponse, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationResponse2, UpdateSettingsData, UpdateSettingsResponse, UpdateSkillData, UpdateSkillResponse, UpdateSlackProviderData, UpdateSlackProviderResponse, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsResponse, UpdateUserData, UpdateUserResponse, UpdateWebhookData, UpdateWebhookProviderData, UpdateWebhookProviderResponse, UpdateWebhookResponse, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradeServiceData, UpgradeServiceResponse, UploadGlobalSkillData, UploadGlobalSkillResponse, UploadReleaseFileData, UploadReleaseFileResponse, UploadSkillData, UploadSkillResponse, UploadSourceFileData, UploadSourceFileResponse, UploadSourceMapData, UploadSourceMapResponse, UploadStaticBundleData, UploadStaticBundleResponse, UpsertSecretData, UpsertSecretResponse, ValidateConnectionData, ValidateConnectionResponse, ValidateEmailData, ValidateEmailResponse2, VerifyAndEnableMfaData, VerifyAndEnableMfaResponse, VerifyDomainData, VerifyDomainResponse, VerifyEmailData, VerifyEmailResponse, VerifyManagedDomainData, VerifyManagedDomainResponse, VerifyMfaChallengeData, VerifyMfaChallengeResponse, WakeEnvironmentData, WakeEnvironmentResponse, WebhookTriggerData, WebhookTriggerResponse2, WorkflowDryRunData, WorkflowDryRunResponse, WriteFileData, WriteFileResponse, WriteFilesData, WriteFilesResponse2 } from '../types.gen'; export type QueryKey = [ Pick & { @@ -5511,6 +5511,33 @@ export const getFileOptions = (options: Options) => queryOptions) => createQueryKey('getFlagSnapshot', options); + +/** + * Every flag for the caller's environment, collapsed to what the evaluator + * needs. + * + * Scope comes from the deployment token, never from the URL: a container's + * baked-in `TEMPS_API_TOKEN` identifies exactly one project (and usually one + * environment), so a compromised app cannot read another tenant's flags by + * changing a path parameter. + * + * Supports `If-None-Match`, so the SDK's background poll is a 304 in the + * common case. + */ +export const getFlagSnapshotOptions = (options?: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getFlagSnapshot({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: getFlagSnapshotQueryKey(options) +}); + export const getIpGeolocationQueryKey = (options: Options) => createQueryKey('getIpGeolocation', options); /** @@ -11512,6 +11539,122 @@ export const getRemoteExternalImageOptions = (options: Options) => createQueryKey('listFlags', options); + +export const listFlagsOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await listFlags({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: listFlagsQueryKey(options) +}); + +export const listFlagsInfiniteQueryKey = (options: Options): QueryKey> => createQueryKey('listFlags', options, true); + +export const listFlagsInfiniteOptions = (options: Options) => { + const opts = infiniteQueryOptions, QueryKey>, number | null | Pick>[0], 'body' | 'headers' | 'path' | 'query'>>( + // @ts-ignore + { + queryFn: async ({ pageParam, queryKey, signal }) => { + // @ts-ignore + const page: Pick>[0], 'body' | 'headers' | 'path' | 'query'> = typeof pageParam === 'object' ? pageParam : { + query: { + page: pageParam + } + }; + const params = createInfiniteParams(queryKey, page); + const { data } = await listFlags({ + ...options, + ...params, + signal, + throwOnError: true + }); + return data; + }, + queryKey: listFlagsInfiniteQueryKey(options) + }); + return opts as Omit; +}; + +export const createFlagMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await createFlag({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + +export const archiveFlagMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await archiveFlag({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + +export const getFlagQueryKey = (options: Options) => createQueryKey('getFlag', options); + +export const getFlagOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getFlag({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: getFlagQueryKey(options) +}); + +export const updateFlagMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await updateFlag({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + +/** + * Set a flag's value in one environment, and/or flip its kill switch. + */ +export const setFlagEnvironmentMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await setFlagEnvironment({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + export const listFunnelsQueryKey = (options: Options) => createQueryKey('listFunnels', options); /** diff --git a/web/src/api/client/index.ts b/web/src/api/client/index.ts index ec6f4eed2..4a0657b39 100644 --- a/web/src/api/client/index.ts +++ b/web/src/api/client/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobHead, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, recordConsoleEvent, recordEventMetrics, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, setDefaultS3Source, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, streamEvents, streamRunEvents, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from './sdk.gen'; -export type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, AcmeOrderResponse, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponse, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponse, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponse, ActivateProviderResponses, ActiveVisitor, ActiveVisitorsQuery, ActiveVisitorsResponse, ActivityDay, ActivityEvent, ActivityGraphQuery, ActivityGraphResponse, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberRequest, AddClusterMemberResponse, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextRequest, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainRequest, AddEnvironmentDomainResponse, AddEnvironmentDomainResponses, AddEventsData, AddEventsError, AddEventsErrors, AddEventsRequest, AddEventsResponse, AddEventsResponse2, AddEventsResponses, AddManagedDomainApiRequest, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponse, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsErrors, AddSessionReplayEventsResponse, AddSessionReplayEventsResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponse, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponse, AdminDrainStatusResponses, AdminGateResponse, AdminGateSource, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponse, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponse, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponse, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponse, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponse, AdminUndrainNodeResponses, AgentConfigResponse, AgentRunLogResponse, AgentRunResponse, AgentRunWithLogsResponse, AgentSandboxSettings, AgentSandboxSettingsMasked, AggregatedBucketItem, AggregatedBucketsQuery, AggregatedBucketsResponse, AggregationLevel, AggregationTemporality, AiAgentBreakdownResponse, AiAgentBreakdownRow, AiAgentDescriptor, AiAgentPageRow, AiAgentPagesResponse, AiAgentTimelineResponse, AiAgentTimelineRow, AiConfigSettings, AiPageBreakdownResponse, AiPageBreakdownRow, AiStatusBreakdownResponse, AiStatusBreakdownRow, AlarmListResponse, AlarmResponse, AlarmSummaryResponse, AlertRuleResponse, AllocEntry, AnalyticsSessionEventsResponse, AnnotatedSpan, AnomalyAlgorithm, AnomalyParams, AnomalyPreviewPointResponse, AnomalyPreviewRequest, AnomalyPreviewResponse, ApiKeyListResponse, ApiKeyResponse, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeRequest, ApplyHostnameModeResponse, ApplyHostnameModeResponses, AppSettings, AppSettingsResponse, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponse, ArchiveConversationResponses, ArchiveMode, AssignRoleData, AssignRoleErrors, AssignRoleRequest, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesErrors, AttachScheduleServicesRequest, AttachScheduleServicesResponse, AttachScheduleServicesResponse2, AttachScheduleServicesResponses, AuditLogIpInfo, AuditLogResponse, AuditLogUserInfo, AuthFlavorDto, AuthResponse, AuthStatusResponse, AuthTokenResponse, AutofixerRunResponse, AutofixerRunWithLogsResponse, AutofixRunConfig, AutoWatchParams, AvailableContainerInfo, AvailablePermissions, BackupAlertListResponse, BackupAlertResponse, BackupResponse, BackupScheduleResponse, BitbucketAuthInput, BlobCopyData, BlobCopyError, BlobCopyErrors, BlobCopyResponse, BlobCopyResponses, BlobDeleteData, BlobDeleteError, BlobDeleteErrors, BlobDeleteResponse, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponse, BlobDisableResponses, BlobDownloadData, BlobDownloadError, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponse, BlobEnableResponses, BlobHeadData, BlobHeadError, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListError, BlobListErrors, BlobListResponse, BlobListResponses, BlobPutData, BlobPutError, BlobPutErrors, BlobPutResponse, BlobPutResponses, BlobResponse, BlobStatusData, BlobStatusErrors, BlobStatusResponse, BlobStatusResponse2, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponse, BlobUpdateResponses, BranchInfo, BranchListResponse, BrowserCount, BrowsersQuery, BuildConfiguration, BuildLimitsSettings, CancelBackupData, CancelBackupError, CancelBackupErrors, CancelBackupResponse, CancelBackupResponse2, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponse, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponse, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponse, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponse, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunErrors, CancelScheduleRunResponse, CancelScheduleRunResponses, CertStatusResponse, ChallengeConfig, ChallengeError, ChallengeValidationStatus, ChangePasswordRequest, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponse, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceRequest, ChangeProjectSourceResponse, ChangeProjectSourceResponses, ChatCompletionChoice, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsErrors, ChatCompletionsResponse, ChatCompletionsResponses, ChatMessage, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponse, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponse, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponse, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponse, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedError, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponse, CheckProviderDeletionSafetyResponses, ChildBackupEntryResponse, ChildBackupListResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsErrors, CleanupExpiredBackupsRequest, CleanupExpiredBackupsResponse, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponse, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveRequest, CliDeviceApproveResponse, CliDeviceApproveResponse2, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponse, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponse, CliDeviceLookupResponse2, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollRequest, CliDevicePollResponse, CliDevicePollResponse2, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartRequest, CliDeviceStartResponse, CliDeviceStartResponse2, CliDeviceStartResponses, ClientOptions, CliLoginRequest, CliLogoutData, CliLogoutErrors, CliLogoutResponse, CliLogoutResponses, CloudflareConfig, CloudProvider, ClusterCapacity, ClusterDnsSettings, ClusterHealthReportResponse, ClusterMemberHealthResponse, ClusterMemberRequest, CmdBody, CmdData, CmdErrors, CmdInner, CmdKillBody, CmdKillData, CmdKillErrors, CmdKillResponse, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponse, CmdResponse2, CmdResponses, CommitExistsResponse, CommitInfo, CommitListResponse, Comparator, ComposePublicPort, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponse, ConfirmPendingActionResponses, ConnectionListQuery, ConnectionListResponse, ConnectionResponse, ConnectionTestResult, ConsoleEventPayload, ContainerActionResponse, ContainerDetailResponse, ContainerEnvironmentVariableValueResponse, ContainerInfoResponse, ContainerInventoryItem, ContainerListResponse, ContainerLogSettings, ContainerLogsQuery, ContainerMetricHistoryPoint, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponse, ContainerMetricsGetHistoryResponses, ContainerMetricsHistoryQuery, ContainerMetricsResponse, ContainerResponse, ContainerRuntimeInfo, ContainerStatsSample, ContentPart, ContextLine, ContextLogsRequest, ContextLogsResponse, ConversationDetailResponse, ConversationResponse, ConversationsQueryParams, ConversationSummary, CopyBlobRequest, CostAnalysis, CreateAgentData, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAlertData, CreateAlertError, CreateAlertErrors, CreateAlertResponse, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleRequest, CreateAlertRuleResponse, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyRequest, CreateApiKeyResponse, CreateApiKeyResponse2, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleErrors, CreateBackupScheduleRequest, CreateBackupScheduleResponse, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponse, CreateBitbucketProviderResponses, CreateBitbucketRequest, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderRequest, CreateCloudflareProviderResponse, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationRequest, CreateConversationResponse, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponse, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardError, CreateDashboardErrors, CreateDashboardRequest, CreateDashboardResponse, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenRequest, CreateDeploymentTokenResponse, CreateDeploymentTokenResponse2, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderRequest, CreateDnsProviderResponse, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainRequest, CreateDomainResponse, CreateDomainResponses, CreatedResource, CreateDsnData, CreateDsnErrors, CreateDsnRequest, CreateDsnResponse, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainRequest, CreateEmailDomainResponse, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderRequest, CreateEmailProviderResponse, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentRequest, CreateEnvironmentResponse, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableRequest, CreateEnvironmentVariableResponse, CreateEnvironmentVariableResponses, CreateExternalServiceRequest, CreateFunnelData, CreateFunnelErrors, CreateFunnelRequest, CreateFunnelResponse, CreateFunnelResponse2, CreateFunnelResponses, CreateFunnelStep, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponse, CreateGenericProviderResponses, CreateGenericRequest, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponse, CreateGiteaPatProviderResponses, CreateGiteaPatRequest, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponse, CreateGithubPatProviderResponses, CreateGitHubPatRequest, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponse, CreateGitlabOauthProviderResponses, CreateGitLabOAuthRequest, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponse, CreateGitlabPatProviderResponses, CreateGitLabPatRequest, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponse, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponse, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponse, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentRequest, CreateIncidentResponse, CreateIncidentResponses, CreateIntegrationBody, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlErrors, CreateIpAccessControlRequest, CreateIpAccessControlResponse, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpRequest, CreateMcpResponse, CreateMcpResponses, CreateMetricAlertRequest, CreateMonitorData, CreateMonitorErrors, CreateMonitorRequest, CreateMonitorResponse, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderRequest, CreateNotificationEmailProviderResponse, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponse, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderRequest, CreateOidcProviderResponse, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingRequest, CreateOidcRoleMappingResponse, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponse, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanRequest, CreatePlanResponse, CreatePlanResponse2, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateRequest, CreateProjectFromTemplateResponse, CreateProjectFromTemplateResponse2, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponse, CreateProjectReleaseResponses, CreateProjectRequest, CreateProjectResponse, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretRequest, CreateProjectSecretResponse, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyErrors, CreateProviderKeyRequest, CreateProviderKeyResponse, CreateProviderKeyResponses, CreateProviderRequest, CreatePrResponse, CreatePrResponse2, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponse, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteRequest, CreateRouteResponse, CreateRouteResponses, CreateS3SourceData, CreateS3SourceError, CreateS3SourceErrors, CreateS3SourceRequest, CreateS3SourceResponse, CreateS3SourceResponses, CreateSandboxBody, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponse, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponse, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillRequest, CreateSkillResponse, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderRequest, CreateSlackProviderResponse, CreateSlackProviderResponses, CreateUserData, CreateUserErrors, CreateUserRequest, CreateUserResponse, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderRequest, CreateWebhookProviderResponse, CreateWebhookProviderResponses, CreateWebhookRequestBody, CreateWebhookResponse, CreateWebhookResponses, CronExecutionInfo, CronInfo, CrossProjectSiblingRef, CrossProjectTraceResponse, CurrentStatusResponse, CustomDomainRequest, CustomDomainResponse, CustomerMovementResponse, DashboardLayout, DashboardProjectsAnalyticsQuery, DashboardProjectsAnalyticsResponse, DashboardSection, DashboardTile, DatabaseMetricsResponse, DatabaseMetricsRow, DataImplication, DataImplicationSeverity, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponse, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAlertData, DeleteAlertError, DeleteAlertErrors, DeleteAlertResponse, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponse, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponse, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupError, DeleteBackupErrors, DeleteBackupResponse, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleErrors, DeleteBackupScheduleResponse, DeleteBackupScheduleResponses, DeleteBlobRequest, DeleteBlobResponse, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponse, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponse, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardError, DeleteDashboardErrors, DeleteDashboardResponse, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponse, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponse, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponse, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponse, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponse, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponse, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponse, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponse, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponse, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponse, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponse, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlErrors, DeleteIpAccessControlResponse, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponse, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponse, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponse, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponse, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponse, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyErrors, DeleteProviderKeyResponse, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponse, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponse, DeleteReleaseSourceMapsResponses, DeleteResponse, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponse, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceErrors, DeleteS3SourceResponse, DeleteS3SourceResponses, DeleteScanData, DeleteScanError, DeleteScanErrors, DeleteScanResponse, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponse, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponse, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponse, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponse, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponse, DeleteStaticBundleResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponse, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponse, DeleteWebhookResponses, DelRequest, DelResponse, DeployFromImageData, DeployFromImageErrors, DeployFromImageRequest, DeployFromImageResponse, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadQuery, DeployFromImageUploadResponse, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticRequest, DeployFromStaticResponse, DeployFromStaticResponses, DeploymentConfig, DeploymentConfigSnapshot, DeploymentConfiguration, DeploymentContainerLogContentResponse, DeploymentContainerLogResponse, DeploymentContainerLogsListResponse, DeploymentEnvironmentResponse, DeploymentJobResponse, DeploymentJobsResponse, DeploymentListResponse, DeploymentMetadata, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponse, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DeploymentResponse, DeploymentStateResponse, DeploymentStrategy, DeploymentTokenListResponse, DeploymentTokenResponse, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponse, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceErrors, DetachScheduleServiceResponse, DetachScheduleServiceResponses, DetectionConfig, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponse, DetectPublicPresetsResponses, DeviceCount, DigestSections, Direction, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponse, DisableBackupScheduleResponses, DisableBlobResponse, DisableKvResponse, DisableMfaData, DisableMfaErrors, DisableMfaRequest, DisableMfaResponse, DisableMfaResponses, DiscoverRequest, DiscoverResponse, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponse, DiscoverWorkloadsResponses, DiskInfo, DiskSpaceAlert, DiskSpaceAlertSettings, DiskSpaceCheckResult, DnsAckRequest, DnsAckResponse, DnsChallengeRecordResult, DnsChangesResponse, DnsCompletionResponse, DnsLookupError, DnsLookupRequest, DnsLookupResponse, DnsProviderCredentials, DnsProviderResponse, DnsProviderSettings, DnsProviderSettingsMasked, DnsProviderType, DnsRecord, DnsRecordChange, DnsRecordContent, DnsRecordResponse, DnsRecordSetupResult, DnsRecordStatusResponse, DnsZone, DockerComposePresetConfig, DockerfilePresetConfig, DockerfileVariant, DockerRegistrySettings, DockerRegistrySettingsMasked, DomainAction, DomainChallengeResponse, DomainData, DomainEnvironmentResponse, DomainError, DomainErrors, DomainPlan, DomainResponse, DomainResponse2, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponse, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponse, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponse, DownloadSkillArchiveResponses, DrainNodeResponse, DrainStatusResponse, DropOffPoint, EmailConfig, EmailDomainResponse, EmailDomainWithDnsResponse, EmailProviderResponse, EmailProviderTypeRoute, EmailRequest, EmailResponse, EmailStatsResponse, EmailStatusData, EmailStatusErrors, EmailStatusResponse, EmailStatusResponse2, EmailStatusResponses, EmailTrackingResponse, EmailTrackingSetupResponse, EmailTrackingStatusResponse, EmbeddingData, EmbeddingInput, EmbeddingRequest, EmbeddingResponse, EmbeddingsData, EmbeddingsError, EmbeddingsErrors, EmbeddingsResponse, EmbeddingsResponses, EmbeddingUsage, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponse, EnableBackupScheduleResponses, EnableBlobRequest, EnableBlobResponse, EnableKvRequest, EnableKvResponse, EnablePgStatStatementsResponse, EndpointDto, EnqueuedJob, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorRequest, EnrichVisitorResponse, EnrichVisitorResponse2, EnrichVisitorResponses, EnrollmentTokenInfo, EnrollmentTokenListResponse, EntityInfoResponse, EntityResponse, EnvironmentConfiguration, EnvironmentDomainResponse, EnvironmentInfo, EnvironmentResponse, EnvironmentVariable, EnvironmentVariableInfo, EnvironmentVariableResponse, EnvironmentVariableValueResponse, EnvVarInput, EnvVarIntegrationInfo, EnvVarResponse, EnvVarTemplateResponse, ErrorDashboardStatsQuery, ErrorDashboardStatsResponse, ErrorEventResponse, ErrorGroupResponse, ErrorGroupStatsResponse, ErrorResponse, ErrorRow, ErrorTimeSeriesDataResponse, ErrorTimeSeriesQuery, EventActivityBucket, EventBreakdown, EventBrowserStats, EventCount, EventCountryStats, EventDetailQuery, EventDetailResponse, EventEntriesQuery, EventEntriesResponse, EventEntryInfo, EventKind, EventMetricsPayload, EventReferrerStats, EventsCountQuery, EventsResponse, EventTimeline, EventTimelineQuery, EventType, EventTypeBreakdown, EventTypeBreakdownQuery, EventTypeResponse, EventTypesResponse, EventVisitorInfo, EventVisitorsQuery, EventVisitorsResponse, ExecBody, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponse, ExecDetachedResponse2, ExecDetachedResponses, ExecErrors, ExecResponse, ExecResponse2, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponse, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportRequest, ExecuteImportResponse, ExecuteImportResponse2, ExecuteImportResponses, ExecuteOperationRequest, ExpireRequest, ExpireResponse, ExplorerSupportResponse, ExtendTimeoutBody, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponse, ExtendTimeoutResponses, ExternalImageResponse, ExternalServiceBackupResponse, ExternalServiceDetails, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceInfo, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceSummary, FieldResponse, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponse, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponse, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponse, FindConversationResponses, FiringSeriesEntry, ForecastAlgorithm, ForecastParams, FullError, FullEvent, FullRequest, FunnelMetricsResponse, FunnelResponse, GatewayStatus, GenAiEvent, GenAiSpanDetail, GenAiTraceDetailResponse, GenAiTraceSummariesResponse, GenAiTraceSummary, GeneralStatsQuery, GeneralStatsResponse, GenerateDockerfileRequest, GenerateDockerfileResponse, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponse, GenerateJoinTokenResponse2, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponse, GeneratePresetDockerfileResponses, GeoLocationResponse, GeoRestrictionsConfig, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponse, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponse, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponse, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponse, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponse, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponse, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesErrors, GetAiAgentPagesResponse, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineErrors, GetAiAgentTimelineResponse, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownErrors, GetAiPageBreakdownResponse, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponse, GetAiStatusBreakdownResponses, GetAlertData, GetAlertError, GetAlertErrors, GetAlertResponse, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponse, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponse, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponse, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponse, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponse, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponse, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponse, GetApiKeyPermissionsResponses, GetApiKeyResponse, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponse, GetAuditLogResponses, GetBackupData, GetBackupError, GetBackupErrors, GetBackupResponse, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponse, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponse, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponse, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponse, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponse, GetChallengeTokenResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponse, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponse, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponse, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponse, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponse, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponse, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponse, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailErrors, GetConversationDetailResponse, GetConversationDetailResponses, GetConversationErrors, GetConversationResponse, GetConversationResponses, GetConversationsData, GetConversationsError, GetConversationsErrors, GetConversationsResponse, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponse, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponse, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponse, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponse, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponse, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponse, GetCustomDomainResponses, GetDashboardData, GetDashboardError, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponse, GetDashboardProjectsAnalyticsResponses, GetDashboardResponse, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponse, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponse, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponse, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponse, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponse, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponse, GetDeploymentOperationStatusResponses, GetDeploymentResponse, GetDeploymentResponses, GetDeploymentsParams, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponse, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponse, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponse, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponse, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponse, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponse, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponse, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponse, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponse, GetDomainOrderResponses, GetDomainResponse, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponse, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponse, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponse, GetEmailProviderResponses, GetEmailResponse, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponse, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponse, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponse, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponse, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponse, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponse, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponse, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponse, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesQuery, GetEnvironmentVariablesResponse, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponse, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponse, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponse, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponse, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponse, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponse, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponse, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponse, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponse, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponse, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponse, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponse, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponse, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponse, GetFileResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsQuery, GetFunnelMetricsResponse, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceErrors, GetGenaiTraceResponse, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponse, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponse, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponse, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponse, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponse, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponse, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponse, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponse, GetGroupedPageMetricsResponses, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponse, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponse, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponse, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponse, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponse, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlErrors, GetIpAccessControlResponse, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationErrors, GetIpGeolocationResponse, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponse, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponse, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanError, GetLatestScanErrors, GetLatestScanResponse, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponse, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponse, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextError, GetLogContextErrors, GetLogContextResponse, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponse, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeErrors, GetMetricsOverTimeResponse, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponse, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponse, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponse, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnRequest, GetOrCreateDsnResponse, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponse, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponse, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponse, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponse, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponse, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponse, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponse, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsErrors, GetPerformanceMetricsResponse, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponse, GetPgUpgradeLogsResponses, GetPgUpgradeResponse, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsErrors, GetPipelineStatsResponse, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponse, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponse, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponse, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingError, GetPricingErrors, GetPricingResponse, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponse, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponse, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponse, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponse, GetProjectResponses, GetProjectsData, GetProjectSecretsQuery, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponse, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysErrors, GetProjectSessionReplaysQuery, GetProjectSessionReplaysResponse, GetProjectSessionReplaysResponse2, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthErrors, GetProjectsHealthResponse, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponse, GetProjectsMonitorHealthResponses, GetProjectsResponse, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponse, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponse, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponse, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponse, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponse, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponse, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponse, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdErrors, GetProxyLogByIdResponse, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponse, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsError, GetProxyLogsErrors, GetProxyLogsResponse, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponse, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponse, GetPublicRepositoryResponses, GetQuotaData, GetQuotaError, GetQuotaErrors, GetQuotaResponse, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponse, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponse, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponse, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponse, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponse, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponse, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponse, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponse, GetRepositoryTagsResponses, GetRequest, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponse, GetResolvedEnvironmentVariableValueResponses, GetResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponse, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunError, GetRestoreRunErrors, GetRestoreRunResponse, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponse, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponse, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponse, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponse, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceError, GetS3SourceErrors, GetS3SourceResponse, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponse, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponse, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentErrors, GetScanByDeploymentResponse, GetScanByDeploymentResponses, GetScanData, GetScanError, GetScanErrors, GetScanResponse, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponse, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponse, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponse, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponse, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponse, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponse, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponse, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponse, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponse, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponse, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponse, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayError, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsErrors, GetSessionReplayEventsResponse, GetSessionReplayEventsResponses, GetSessionReplayResponse, GetSessionReplayResponse2, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponse, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponse, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponse, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponse, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponse, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponse, GetTagsByRepositoryIdResponses, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsErrors, GetTimeBucketStatsResponse, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsError, GetTodayStatsErrors, GetTodayStatsResponse, GetTodayStatsResponses, GetTraceData, GetTraceError, GetTraceErrors, GetTraceResponse, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceErrors, GetUnifiedTraceResponse, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponse, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsQuery, GetUniqueEventsResponse, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponse, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponse, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderErrors, GetUsageByProviderResponse, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentError, GetUsageRecentErrors, GetUsageRecentResponse, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryErrors, GetUsageSummaryResponse, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesErrors, GetUsageTimeseriesResponse, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsErrors, GetUsageTopModelsResponse, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponse, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponse, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponse, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponse, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponse, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponse, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsErrors, GetVisitorSessionsQuery, GetVisitorSessionsResponse, GetVisitorSessionsResponse2, GetVisitorSessionsResponses, GetVisitorsResponse, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponse, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponse, GetWebhookResponses, GitPushEvent, GitRefResponse, GitSourcePlan, GlobalConversationResponse, GlobalEventStatsResponse, GlobalMrrResponse, GlobalRecentEventResponse, GlobalRevenueSummaryResponse, GroupedPageMetric, GroupedPageMetricsQuery, GroupedPageMetricsResponse, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponse, HasAnalyticsEventsResponse2, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponse, HasErrorGroupsResponse2, HasErrorGroupsResponses, HasEventsQuery, HasEventsResponse, HasMetricsQuery, HasMetricsResponse, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsErrors, HasPerformanceMetricsResponse, HasPerformanceMetricsResponses, HealthCheckConfiguration, HealthCheckEntryResponse, HealthResponse, HealthStatus, HealthSummary, HeartbeatApiRequest, HeartbeatResponse, HierarchyLevel, HistogramSummary, HostnameChange, HostnamePreviewResponse, HourlyPageSessions, HourlyVisitsQuery, HttpChallengeDebugResponse, ImportCredentials, ImportExecutionStatus, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceRequest, ImportExternalServiceResponse, ImportExternalServiceResponses, ImportOutcomeResponse, ImportPlan, ImportRowErrorResponse, ImportSelector, ImportSource, ImportSourceCapabilities, ImportSourceInfo, ImportStatusResponse, IncidentBucket, IncidentBucketedResponse, IncidentResponse, IncidentUpdateResponse, IncrRequest, IncrResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsError, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsError, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponse, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathError, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesError, IngestTracesErrors, IngestTracesResponses, InitAuthResponse, InitSessionReplayData, InitSessionReplayError, InitSessionReplayErrors, InitSessionReplayResponse, InitSessionReplayResponses, Insight, InsightSeverity, InsightsResponse, InsightStatus, IntegrationResponse, IpAccessControlQuery, IpAccessControlResponse, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponse, JobStatusResponse2, JobStatusResponses, JobSummaryResponse, JoinTokenStatusResponse, JourneyEvent, JourneySession, KeysRequest, KeysResponse, KillJobBody, KillJobData, KillJobErrors, KillJobResponse, KillJobResponses, KnownAiAgentsResponse, KvDelData, KvDelErrors, KvDelResponse, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponse, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponse, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponse, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponse, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponse, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponse, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponse, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponse, KvStatusResponse2, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponse, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponse, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponse, LatestRunForSourceResponses, LemonSqueezyConfig, LetsEncryptSettings, LineContext, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponse, LinkCustomDomainToCertificateResponses, LinkServiceRequest, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponse, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponse, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponse, ListAgentsResponse2, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponse, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponse, ListAlertRulesResponses, ListAlertsData, ListAlertsError, ListAlertsErrors, ListAlertsResponse, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponse, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponse, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysQuery, ListApiKeysResponse, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsQuery, ListAuditLogsResponse, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponse, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsErrors, ListBackupAlertsResponse, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenErrors, ListBackupChildrenResponse, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesErrors, ListBackupSchedulesResponse, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponse, ListBackupsForScheduleResponses, ListBlobsQuery, ListBlobsResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponse, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponse, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponse, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponse, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponse, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponse, ListCustomDomainsForProjectResponses, ListCustomDomainsResponse, ListDashboardsData, ListDashboardsError, ListDashboardsErrors, ListDashboardsResponse, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponse, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensQuery, ListDeploymentTokensResponse, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponse, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponse, ListDomainsResponse2, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponse, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponse, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponse, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponse, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesQuery, ListEntitiesResponse, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsQuery, ListErrorEventsResponse, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsQuery, ListErrorGroupsResponse, ListErrorGroupsResponses, ListEventsData, ListEventsResponse, ListEventsResponses, ListEventTypesData, ListEventTypesResponse, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponse, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponse, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponse, ListExternalServiceBackupsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponse, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponse, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponse, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponse, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsError, ListInsightsErrors, ListInsightsResponse, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlErrors, ListIpAccessControlResponse, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponse, ListJobsResponse2, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsErrors, ListKnownAiAgentsResponse, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponse, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponse, ListMcpsResponse2, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysErrors, ListMetricLabelKeysResponse, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesErrors, ListMetricLabelValuesResponse, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesError, ListMetricNamesErrors, ListMetricNamesResponse, ListMetricNamesResponses, ListModelsData, ListModelsError, ListModelsErrors, ListModelsResponse, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponse, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponse, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponse, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponse, ListOnDemandCertsResponse2, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponse, ListOrdersResponse2, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponse, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponse, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponse, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponse, ListPresetsResponse2, ListPresetsResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponse, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansError, ListProjectScansErrors, ListProjectScansResponse, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponse, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponse, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponse, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponse, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysError, ListProviderKeysErrors, ListProviderKeysResponse, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponse, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponse, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponse, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponse, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponse, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponse, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponse, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponse, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponse, ListRoutesResponses, ListRunsResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesErrors, ListS3SourcesResponse, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponse, ListSandboxesResponse2, ListSandboxesResponses, ListScansQuery, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsErrors, ListScheduleRunJobsResponse, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsErrors, ListScheduleRunsResponse, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesErrors, ListScheduleServicesResponse, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponse, ListSecretsResponse2, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponse, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponse, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesErrors, ListServiceSchedulesResponse, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponse, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponse, ListSkillsResponse2, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsErrors, ListSourceBackupsResponse, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponse, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponse, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponse, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponse, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponse, ListSyncedRepositoriesResponses, ListTagsResponse, ListTemplatesQuery, ListTemplatesResponse, ListUsersData, ListUsersErrors, ListUsersResponse, ListUsersResponses, ListVulnerabilitiesQuery, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponse, ListWebhooksResponses, LiveVisitorInfo, LiveVisitorsListResponse, LocationCount, LocationGranularity, LocationInfo, LoginData, LoginErrors, LoginRequest, LoginResponse, LoginResponses, LogLevel, LogoutData, LogoutErrors, LogoutResponses, LogRecord, LogSearchLine, LogSeverity, LogSource, LogsQuery, LogsResponse, LogStream, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsErrors, LookupDnsARecordsResponse, LookupDnsARecordsResponses, ManagedDomainResponse, ManualAction, ManualActionTiming, McpDefinitionResponse, MessageContent, MessagePart, MessageResponse, MeteredMode, MetricAggregation, MetricBucket, MetricDataPoint, MetricsOverTimeResponse, MetricsQuery, MetricsRangeQuery, MetricsStatusResponse, MetricsStoreKind, MetricsSummaryResponse, MetricType, MfaRequiredResponse, MfaSetupResponse, MfaVerificationRequest, MigrationStep, MigrationSummary, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenRequest, MintEnrollmentTokenResponse, MintEnrollmentTokenResponse2, MintEnrollmentTokenResponses, MiscResult, MkdirBody, MkdirData, MkdirErrors, MkdirResponse, MkdirResponses, ModelInfo, ModelListResponse, ModelPricing, ModelUsage, MonitoringSettings, MonitoringSettingsMasked, MonitorResponse, MonitorStatus, MrrBucketResponse, MultiNodeSettings, MultiNodeSettingsMasked, MxResult, NavEntry, NavSection, NetworkConfiguration, NetworkMode, NixpacksPresetConfig, NixpacksProvider, NodeContainerListResponse, NodeContainerResponse, NodeCostInfo, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponse, NodeHeartbeatResponses, NodeInfoResponse, NodeListResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponse, NodeMetricsGetRangeResponses, NotificationPreferencesResponse, NotificationProviderResponse, ObservabilityCompressionSettings, ObservabilityEvent, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventErrors, ObservabilityFullEventResponse, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsErrors, ObservabilityListEventsResponse, ObservabilityListEventsResponses, ObservabilityRetentionSettings, OidcCallbackData, OidcProviderResponse, OidcProvidersListResponse, OidcProviderSummary, OidcProviderUserResponse, OidcRoleMappingResponse, OidcTestConnectionResponse, OnDemandCertAttemptResponse, OnDemandCertRow, OnDemandTlsSettings, OpenAiError, OpenAiErrorResponse, OperatingSystemCount, OperationResultResponse, OperationResultsResponse, OtelDashboardResponse, OtelDashboardsResponse, OtelMetricAlertRuleResponse, OtelMetricAlertsResponse, OtelMetricLabelKeysResponse, OtelMetricLabelValuesResponse, OtelMetricNamesResponse, OtelMetricsResponse, OutlierAlgorithm, OutlierParams, OverprovisioningAssessment, OverprovisioningVerdict, PageActivityBucket, PageCountryStats, PageFlowEntry, PageFlowQuery, PageFlowResponse, PageHourlySessionsQuery, PageHourlySessionsResponse, PagePathDetailQuery, PagePathDetailResponse, PagePathInfo, PagePathSparkline, PagePathSparklinePoint, PagePathsQuery, PagePathsResponse, PagePathsSparklineQuery, PagePathsSparklineResponse, PagePathVisitorsQuery, PagePathVisitorsResponse, PageReferrerStats, PagesComparisonResponse, PageSessionComparison, PageSessionStats, PageSessionStatsQuery, PageTransition, PageVisit, PageVisitorSession, PaginatedEmailsResponse, PaginatedEntitiesResponse, PaginatedErrorEventsResponse, PaginatedErrorGroupsResponse, PaginatedEventsResponse, PaginatedExternalImagesResponse, PaginatedProjectList, PaginatedStaticBundlesResponse, Pagination, PaginationMeta, PaginationParams, PasswordProtectionConfig, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponse, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PatchPreviewGatewaySettingsResponses, PatchSettingsRequest, PathVisitors, PathVisitorsAnalyticsQuery, PathVisitorsResponse, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponse, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponse, PauseSandboxResponses, PeerEntry, PeerListResponse, PendingActionResponse, PerformanceMetricsQuery, PerformanceMetricsResponse, PermissionInfo, PgUpgradeLogResponse, PgUpgradeResponse, PipelineStats, PipelineStatsResponse, PlanComplexity, PlanMetadata, PlanRestoreData, PlanRestoreError, PlanRestoreErrors, PlanRestoreResponse, PlanRestoreResponses, PlanSourceBackup, PlanTarget, PlatformInfo, PluginManifest, PortMapping, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponse, PostDnsAckResponses, PostgresWalHealth, PresetConfigSchema, PresetInfo, PresetResponse, PreviewAlertData, PreviewAlertError, PreviewAlertErrors, PreviewAlertResponse, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponse, PreviewFunnelMetricsResponses, PreviewGatewaySettings, PreviewGatewaySettingsMasked, PreviewGatewaySettingsResponse, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponse, PreviewHostnameModeResponses, PricingResponse, ProblemDetails, ProjectConfiguration, ProjectDashboardAnalytics, ProjectDsnResponse, ProjectHealthSummary, ProjectInfo, ProjectMonitorHealth, ProjectPresetResponse, ProjectQuery, ProjectRef, ProjectResponse, ProjectSecretEnvironmentInfo, ProjectSecretResponse, ProjectServiceInfo, ProjectsHealthResponse, ProjectsMonitorHealthResponse, ProjectStatisticsResponse, ProjectStatsBreakdown, ProjectType, ProjectUsageInfoResponse, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentRequest, PromoteDeploymentResponse, PromoteDeploymentResponses, PropertyBreakdownItem, PropertyBreakdownQuery, PropertyBreakdownResponse, PropertyColumn, PropertyTimelineItem, PropertyTimelineQuery, PropertyTimelineResponse, Protocol, ProviderCatalogDto, ProviderCatalogResponse, ProviderConfig, ProviderConfigMasked, ProviderDeletionCheckResponse, ProviderDescriptor, ProviderKeyResponse, ProviderMetadata, ProviderResponse, ProviderUsage, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponse, ProvisionDomainResponses, ProvisionResponse, ProxyLogResponse, ProxyLogsPaginatedResponse, ProxyRequest, PublicHostnameStrategy, PublicPresetResponse, PublicRepositoryInfo, PurgeLogsRequest, PurgeProjectLogsData, PurgeProjectLogsError, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushedExternalImageResponse, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponse, PushExternalImageResponses, PushImageRequest, QueryDataData, QueryDataErrors, QueryDataRequest, QueryDataResponse, QueryDataResponse2, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesErrors, QueryGenaiTracesResponse, QueryGenaiTracesResponses, QueryLogsData, QueryLogsError, QueryLogsErrors, QueryLogsResponse, QueryLogsResponses, QueryMetricsData, QueryMetricsError, QueryMetricsErrors, QueryMetricsResponse, QueryMetricsResponses, QueryTracesData, QueryTracesError, QueryTracesErrors, QueryTracesResponse, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesErrors, QueryTraceSummariesResponse, QueryTraceSummariesResponses, QuotaResponse, RateLimitConfig, RateLimitSettings, ReachabilityStatus, ReadFileData, ReadFileErrors, ReadFileResponse, ReadFileResponse2, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RecentActivityQuery, RecentActivityResponse, RecentEventResponse, RecentQueryParams, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponse, RecordEventMetricsResponses, RecordListResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsErrors, RecordSpeedMetricsResponse, RecordSpeedMetricsResponses, RecoveryTarget, ReferrerCount, ReferrersAnalyticsQuery, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponse, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnRequest, RegenerateDsnResponse, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponse, RegisterExternalImageResponses, RegisterImageRequest, RegisterNodeApiRequest, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponse, RegisterNodeResponse2, RegisterNodeResponses, RegisterRequest, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponse, ReinstallGitlabWebhookResponses, ReinstallWebhookResponse, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponse, RejectPendingActionResponses, ReleaseListResponse, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponse, ReloadPluginsResponses, ReloadResponse, RemoteDeploymentResponse, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponse, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponse, RemoveManagedDomainResponses, RemoveNodeResponse, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponse, RemoveRoleResponses, RenameConversationData, RenameConversationErrors, RenameConversationRequest, RenameConversationResponse, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponse, RenewDomainResponses, RepositoryListQuery, RepositoryListResponse, RepositoryPresetResponse, RepositoryResponse, RepositorySyncStartedResponse, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponse, RequestPasswordResetResponses, RequestRow, ResetPasswordData, ResetPasswordErrors, ResetPasswordRequest, ResetPasswordResponse, ResetPasswordResponses, ResizeSandboxBody, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponse, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, ResolvedEnvVarResponse, ResolvedEnvVarSource, ResourceCounts, ResourceFootprint, ResourceInfo, ResourceLimitApplyResult, ResourceLimits, ResourceLimitsResponse, ResourceLimitsUpdateResponse, ResourcesBody, RestartContainerData, RestartContainerErrors, RestartContainerResponse, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponse, RestartSandboxResponses, RestoreCapabilities, RestoreCapabilitiesResponse, RestorePlan, RestoreRequestMode, RestoreRunView, RestoreUserData, RestoreUserErrors, RestoreUserResponse, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponse, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponse, ResumeSandboxResponses, RetentionCleanupFailure, RetentionCleanupReport, RetryClusterData, RetryClusterErrors, RetryClusterRequest, RetryClusterResponse, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponse, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponse, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponse, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponse, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponse, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponse, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponse, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponse, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponse, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponse, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponse, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueRotateTokenResponses, RevenueRow, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponse, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponse, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponse, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponse, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponse, RevokeJoinTokenResponses, RiskLevel, RoleInfo, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponse, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponse, RollbackToDeploymentResponses, RootfsCacheEntry, RootfsGcData, RootfsGcReport, RootfsGcResponses, RootfsReport, RootfsReportData, RootfsReportResponses, RootfsVmEntry, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponse, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponse, RotateDeploymentTokenResponses, RouteRefreshResponse, RouteResponse, RouteRole, RouteUser, RouteUserWithRoles, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceErrors, RunBackupForSourceResponse, RunBackupForSourceResponses, RunBackupRequest, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponse, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupErrors, RunExternalServiceBackupRequest, RunExternalServiceBackupResponse, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowError, RunScheduleNowErrors, RunScheduleNowResponse, RunScheduleNowResponses, S3ConnectionTestResponse, S3CredentialsResponse, S3SourceResponse, S3SourceResponseWritable, SandboxDomainResponse, SandboxEvent, SandboxEventsResponse, SandboxInner, SandboxResponse, SandboxRoute, SandboxStatusResponse, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenRequest, SaveAgentTokenResponse, SaveAgentTokenResponse2, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponse, SaveAiProviderCredentialResponses, SaveCredentialRequest, SaveCredentialResponse, ScalewayCredentialsRequest, ScanResponse, ScheduleRunEntry, ScheduleRunJobEntry, ScheduleRunListResponse, ScheduleRunResponse, ScheduleRunSummary, ScheduleRunSummaryList, ScreenshotSettings, SearchLogsData, SearchLogsError, SearchLogsErrors, SearchLogsRequest, SearchLogsResponse, SearchLogsResponse2, SearchLogsResponses, SearchMode, Seasonality, SecretResponse, SecurityConfig, SecurityHeadersConfig, SecurityHeadersSettings, SendEmailData, SendEmailErrors, SendEmailRequestBody, SendEmailResponse, SendEmailResponseBody, SendEmailResponses, SendMessageRequest, SensitiveConfigValueResponse, SensitiveMcpConfigValueResponse, SensitiveValueResponse, SentryChunkUploadResponse, SentryCreateReleaseRequest, SentryEventRequest, SentryEventResponse, SentryReleaseFileResponse, SentryReleaseProjectRef, SentryReleaseResponse, SeriesStateEntry, ServiceAccessInfo, ServiceAction, ServiceAlertRuleResponse, ServiceBackupEntryResponse, ServiceBackupListResponse, ServiceCreateAlertRuleRequest, ServiceHealthResponse, ServiceHealthStatusBatchResponse, ServiceHealthStatusEntryResponse, ServiceMemberInfo, ServiceParameter, ServicePlan, ServiceResourceLimits, ServiceRuntimeReport, ServiceStatsReport, ServiceTypeInfo, ServiceTypeRoute, ServiceUpdateAlertRuleRequest, SesCredentialsRequest, SessionDetails, SessionDetailsQuery, SessionEvent, SessionEventDto, SessionEventsQuery, SessionEventsResponse, SessionLogsQuery, SessionLogsResponse, SessionReplayEventsRequest, SessionReplayInfoDto, SessionReplayInitRequest, SessionReplayInitResponse, SessionReplayWithEventsDto, SessionReplayWithVisitorDto, SessionRequestLog, SessionSummary, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceErrors, SetDefaultS3SourceResponse, SetDefaultS3SourceResponses, SetPreviewPasswordBody, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponse, SetPreviewPasswordResponse2, SetPreviewPasswordResponses, SetRequest, SetResponse, SettingsUpdateResponse, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeRequest, SetupDnsChallengeResponse, SetupDnsChallengeResponse2, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsRequest, SetupDnsResponse, SetupDnsResponse2, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponse, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponse, SetupMfaResponses, SiblingRef, SkillDefinitionResponse, SlackConfig, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponse, SleepEnvironmentResponses, SlowQueriesResponse, SlowQueryRow, SmartFilter, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponse, SmokeTestAgentResponses, SmokeTestResponse, SmtpCredentialsRequest, SmtpEncryptionRoute, SmtpResult, SourceBackupEntry, SourceBackupIndexResponse, SourceBody, SourceFileListResponse, SourceFileResponse, SourceMapListResponse, SourceMapResponse, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponse, SourceSandboxResponses, SourceType, SpanEvent, SpanKind, SpanRecord, SpanRow, SpanStatusCode, SpeedMetricsPayload, SpeedSegmentFilters, StaleSlot, StartAnalysisData, StartAnalysisErrors, StartAnalysisRequest, StartAnalysisResponse, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponse, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeRequest, StartPgUpgradeResponse, StartPgUpgradeResponses, StartRestoreData, StartRestoreError, StartRestoreErrors, StartRestoreRequest, StartRestoreResponse, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponse, StartServiceResponses, StaticBundleResponse, StaticParams, StaticPresetConfig, StatPathData, StatPathErrors, StatPathResponse, StatPathResponses, StatResponse, StatsFilters, StatusBucket, StatusBucketedResponse, StatusCodeCount, StatusCodesQuery, StatusPageOverview, StepConversionResponse, StepResourceType, StepResult, StopContainerData, StopContainerErrors, StopContainerResponse, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponse, StopSandboxResponses, StopSequence, StopServiceData, StopServiceErrors, StopServiceResponse, StopServiceResponses, StorageQuota, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, StripeConfig, SyncedRepositoryListQuery, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponse, SyncRepositoriesResponses, SyntaxResult, TagInfo, TagListResponse, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsError, TailLogsErrors, TailLogsRequest, TailLogsResponses, TargetRecommendation, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponse, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponse, TeardownEnvironmentResponses, TemplateResponse, TestEmailRequest, TestEmailResponse, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponse, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponse, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponse, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdErrors, TestProviderKeyByIdResponse, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineErrors, TestProviderKeyInlineResponse, TestProviderKeyInlineResponses, TestProviderKeyRequest, TestProviderKeyResponse, TestProviderResponse, TestProviderResponse2, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponse, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionErrors, TestS3SourceConnectionResponse, TestS3SourceConnectionResponses, TimeBucketStats, TimeBucketStatsResponse, TimeseriesBucket, TimeseriesQueryParams, TlsMode, TodayStatsResponse, ToggleDeploymentMetricsRequest, ToggleServiceMetricsRequest, TokenRenewalRequest, ToolCallEvent, ToolInfo, ToolResultEvent, TopModelsQueryParams, TraceProjectRef, TracesResponse, TraceSummariesResponse, TraceSummary, TrackClickData, TrackClickErrors, TrackedLinkResponse, TrackingEventResponse, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentRequest, TriggerAgentResponse, TriggerAgentResponses, TriggerDigestResponse, TriggerPipelinePayload, TriggerPipelineResponse, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponse, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanError, TriggerScanErrors, TriggerScanRequest, TriggerScanResponse, TriggerScanResponse2, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponse, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponse, TriggerWeeklyDigestResponses, TtlRequest, TtlResponse, TxtRecord, UiManifest, UiRoute, UndrainNodeResponse, UnifiedTrace, UniqueCountsQuery, UniqueCountsResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponse, UnlinkServiceFromProjectResponses, UnsupportedFeature, UpdateAdminGateRequest, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderRequest, UpdateAiProviderResponse, UpdateAiProviderResponse2, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertError, UpdateAlertErrors, UpdateAlertResponse, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleRequest, UpdateAlertRuleResponse, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyRequest, UpdateApiKeyResponse, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployRequest, UpdateAutomaticDeployResponse, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleErrors, UpdateBackupScheduleRequest, UpdateBackupScheduleResponse, UpdateBackupScheduleResponses, UpdateBlobRequest, UpdateBlobResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderRequest, UpdateCloudflareProviderResponse, UpdateCloudflareProviderResponses, UpdateConfigBody, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponse, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainRequest, UpdateCustomDomainResponse, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardError, UpdateDashboardErrors, UpdateDashboardRequest, UpdateDashboardResponse, UpdateDashboardResponses, UpdateDeploymentConfigRequest, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenRequest, UpdateDeploymentTokenResponse, UpdateDeploymentTokenResponses, UpdateDnsProviderRequest, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderRequest, UpdateEmailProviderResponse, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsRequest, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainRequest, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableRequest, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupRequest, UpdateErrorGroupResponses, UpdateExternalServiceRequest, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponse, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsRequest, UpdateGitSettingsResponse, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponse, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponse, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusRequest, UpdateIncidentStatusResponse, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlErrors, UpdateIpAccessControlRequest, UpdateIpAccessControlResponse, UpdateIpAccessControlResponses, UpdateKvRequest, UpdateKvResponse, UpdateManagedDomainApiRequest, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponse, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpRequest, UpdateMcpResponse, UpdateMcpResponses, UpdateMetricAlertRequest, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderRequest, UpdateNotificationEmailProviderResponse, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponse, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderRequest, UpdateOidcProviderResponse, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesRequest, UpdatePreferencesResponse, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponse, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretRequest, UpdateProjectSecretResponse, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsRequest, UpdateProjectSettingsResponse, UpdateProjectSettingsResponses, UpdateProviderCredentialsRequest, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyErrors, UpdateProviderKeyRequest, UpdateProviderKeyResponse, UpdateProviderKeyResponses, UpdateProviderRequest, UpdateProviderResponse, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteRequest, UpdateRouteResponse, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceErrors, UpdateS3SourceRequest, UpdateS3SourceResponse, UpdateS3SourceResponses, UpdateSecretBody, UpdateSelfData, UpdateSelfErrors, UpdateSelfRequest, UpdateSelfResponse, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponse, UpdateServiceResourcesResponses, UpdateServiceResponse, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationErrors, UpdateSessionDurationRequest, UpdateSessionDurationResponse, UpdateSessionDurationResponse2, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponse, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillRequest, UpdateSkillResponse, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderRequest, UpdateSlackProviderResponse, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsErrors, UpdateSpeedMetricsPayload, UpdateSpeedMetricsResponse, UpdateSpeedMetricsResponses, UpdateStatusResponse, UpdateTokenRequest, UpdateTokenResponse, UpdateUserData, UpdateUserErrors, UpdateUserRequest, UpdateUserResponse, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderRequest, UpdateWebhookProviderResponse, UpdateWebhookProviderResponses, UpdateWebhookRequestBody, UpdateWebhookResponse, UpdateWebhookResponses, UpgradeExternalServiceRequest, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradePreviewGatewayResponses, UpgradeRequest, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponse, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponse, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponse, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponse, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponse, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponse, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponse, UploadStaticBundleResponses, UpsertAgentRequest, UpsertSecretData, UpsertSecretErrors, UpsertSecretRequest, UpsertSecretResponse, UpsertSecretResponses, UptimeDataPoint, UptimeHistoryResponse, UsageFilter, UsageInfo, UsageLogEntry, UsageLogPage, UsageQueryParams, UsageSource, UsageSummary, UserResponse, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponse, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailRequest, ValidateEmailResponse, ValidateEmailResponse2, ValidateEmailResponses, ValidationLevel, ValidationReport, ValidationResponse, ValidationResult, ValidationStatus, ValidationSummary, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponse, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponse, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponse, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponse, VerifyMfaChallengeResponses, VerifyMfaRequest, ViewItem, ViewsOverTime, ViewsOverTimeQuery, VisitorDetails, VisitorFacets, VisitorFacetsQuery, VisitorFacetValue, VisitorInfo, VisitorJourneyQuery, VisitorJourneyResponse, VisitorLocationsQuery, VisitorRecord, VisitorSegmentFilters, VisitorSessionsQuery, VisitorSessionsResponse, VisitorsListQuery, VisitorsResponse, VisitorStats, VisitorWithGeolocation, VolumeMount, VolumeType, VulnerabilityResponse, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponse, WakeEnvironmentResponses, WalWarning, WalWarningSeverity, WebhookConfig, WebhookDeliveryResponse, WebhookResponse, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerRequest, WebhookTriggerResponse, WebhookTriggerResponse2, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunRequest, WorkflowDryRunResponse, WorkflowDryRunResponses, WorkloadDescriptor, WorkloadId, WorkloadStatus, WorkloadType, WriteFileBody, WriteFileData, WriteFileErrors, WriteFileResponse, WriteFileResponses, WriteFilesBody, WriteFilesData, WriteFilesErrors, WriteFilesResponse, WriteFilesResponse2, WriteFilesResponses, ZoneListResponse } from './types.gen'; +export { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobHead, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, recordConsoleEvent, recordEventMetrics, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, streamEvents, streamRunEvents, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from './sdk.gen'; +export type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, AcmeOrderResponse, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponse, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponse, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponse, ActivateProviderResponses, ActiveVisitor, ActiveVisitorsQuery, ActiveVisitorsResponse, ActivityDay, ActivityEvent, ActivityGraphQuery, ActivityGraphResponse, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberRequest, AddClusterMemberResponse, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextRequest, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainRequest, AddEnvironmentDomainResponse, AddEnvironmentDomainResponses, AddEventsData, AddEventsError, AddEventsErrors, AddEventsRequest, AddEventsResponse, AddEventsResponse2, AddEventsResponses, AddManagedDomainApiRequest, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponse, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsErrors, AddSessionReplayEventsResponse, AddSessionReplayEventsResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponse, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponse, AdminDrainStatusResponses, AdminGateResponse, AdminGateSource, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponse, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponse, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponse, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponse, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponse, AdminUndrainNodeResponses, AgentConfigResponse, AgentRunLogResponse, AgentRunResponse, AgentRunWithLogsResponse, AgentSandboxSettings, AgentSandboxSettingsMasked, AggregatedBucketItem, AggregatedBucketsQuery, AggregatedBucketsResponse, AggregationLevel, AggregationTemporality, AiAgentBreakdownResponse, AiAgentBreakdownRow, AiAgentDescriptor, AiAgentPageRow, AiAgentPagesResponse, AiAgentTimelineResponse, AiAgentTimelineRow, AiConfigSettings, AiPageBreakdownResponse, AiPageBreakdownRow, AiStatusBreakdownResponse, AiStatusBreakdownRow, AlarmListResponse, AlarmResponse, AlarmSummaryResponse, AlertRuleResponse, AllocEntry, AnalyticsSessionEventsResponse, AnnotatedSpan, AnomalyAlgorithm, AnomalyParams, AnomalyPreviewPointResponse, AnomalyPreviewRequest, AnomalyPreviewResponse, ApiKeyListResponse, ApiKeyResponse, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeRequest, ApplyHostnameModeResponse, ApplyHostnameModeResponses, AppSettings, AppSettingsResponse, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponse, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponse, ArchiveFlagResponse2, ArchiveFlagResponses, ArchiveMode, AssignRoleData, AssignRoleErrors, AssignRoleRequest, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesErrors, AttachScheduleServicesRequest, AttachScheduleServicesResponse, AttachScheduleServicesResponse2, AttachScheduleServicesResponses, AuditLogIpInfo, AuditLogResponse, AuditLogUserInfo, AuthFlavorDto, AuthResponse, AuthStatusResponse, AuthTokenResponse, AutofixerRunResponse, AutofixerRunWithLogsResponse, AutofixRunConfig, AutoWatchParams, AvailableContainerInfo, AvailablePermissions, BackupAlertListResponse, BackupAlertResponse, BackupResponse, BackupScheduleResponse, BitbucketAuthInput, BlobCopyData, BlobCopyError, BlobCopyErrors, BlobCopyResponse, BlobCopyResponses, BlobDeleteData, BlobDeleteError, BlobDeleteErrors, BlobDeleteResponse, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponse, BlobDisableResponses, BlobDownloadData, BlobDownloadError, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponse, BlobEnableResponses, BlobHeadData, BlobHeadError, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListError, BlobListErrors, BlobListResponse, BlobListResponses, BlobPutData, BlobPutError, BlobPutErrors, BlobPutResponse, BlobPutResponses, BlobResponse, BlobStatusData, BlobStatusErrors, BlobStatusResponse, BlobStatusResponse2, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponse, BlobUpdateResponses, BranchInfo, BranchListResponse, BrowserCount, BrowsersQuery, BuildConfiguration, BuildLimitsSettings, CancelBackupData, CancelBackupError, CancelBackupErrors, CancelBackupResponse, CancelBackupResponse2, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponse, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponse, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponse, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponse, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunErrors, CancelScheduleRunResponse, CancelScheduleRunResponses, CertStatusResponse, ChallengeConfig, ChallengeError, ChallengeValidationStatus, ChangePasswordRequest, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponse, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceRequest, ChangeProjectSourceResponse, ChangeProjectSourceResponses, ChatCompletionChoice, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsErrors, ChatCompletionsResponse, ChatCompletionsResponses, ChatMessage, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponse, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponse, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponse, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponse, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedError, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponse, CheckProviderDeletionSafetyResponses, ChildBackupEntryResponse, ChildBackupListResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsErrors, CleanupExpiredBackupsRequest, CleanupExpiredBackupsResponse, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponse, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveRequest, CliDeviceApproveResponse, CliDeviceApproveResponse2, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponse, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponse, CliDeviceLookupResponse2, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollRequest, CliDevicePollResponse, CliDevicePollResponse2, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartRequest, CliDeviceStartResponse, CliDeviceStartResponse2, CliDeviceStartResponses, ClientOptions, CliLoginRequest, CliLogoutData, CliLogoutErrors, CliLogoutResponse, CliLogoutResponses, CloudflareConfig, CloudProvider, ClusterCapacity, ClusterDnsSettings, ClusterHealthReportResponse, ClusterMemberHealthResponse, ClusterMemberRequest, CmdBody, CmdData, CmdErrors, CmdInner, CmdKillBody, CmdKillData, CmdKillErrors, CmdKillResponse, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponse, CmdResponse2, CmdResponses, CommitExistsResponse, CommitInfo, CommitListResponse, Comparator, ComposePublicPort, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponse, ConfirmPendingActionResponses, ConnectionListQuery, ConnectionListResponse, ConnectionResponse, ConnectionTestResult, ConsoleEventPayload, ContainerActionResponse, ContainerDetailResponse, ContainerEnvironmentVariableValueResponse, ContainerInfoResponse, ContainerInventoryItem, ContainerListResponse, ContainerLogSettings, ContainerLogsQuery, ContainerMetricHistoryPoint, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponse, ContainerMetricsGetHistoryResponses, ContainerMetricsHistoryQuery, ContainerMetricsResponse, ContainerResponse, ContainerRuntimeInfo, ContainerStatsSample, ContentPart, ContextLine, ContextLogsRequest, ContextLogsResponse, ConversationDetailResponse, ConversationResponse, ConversationsQueryParams, ConversationSummary, CopyBlobRequest, CostAnalysis, CreateAgentData, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAlertData, CreateAlertError, CreateAlertErrors, CreateAlertResponse, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleRequest, CreateAlertRuleResponse, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyRequest, CreateApiKeyResponse, CreateApiKeyResponse2, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleErrors, CreateBackupScheduleRequest, CreateBackupScheduleResponse, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponse, CreateBitbucketProviderResponses, CreateBitbucketRequest, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderRequest, CreateCloudflareProviderResponse, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationRequest, CreateConversationResponse, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponse, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardError, CreateDashboardErrors, CreateDashboardRequest, CreateDashboardResponse, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenRequest, CreateDeploymentTokenResponse, CreateDeploymentTokenResponse2, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderRequest, CreateDnsProviderResponse, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainRequest, CreateDomainResponse, CreateDomainResponses, CreatedResource, CreateDsnData, CreateDsnErrors, CreateDsnRequest, CreateDsnResponse, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainRequest, CreateEmailDomainResponse, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderRequest, CreateEmailProviderResponse, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentRequest, CreateEnvironmentResponse, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableRequest, CreateEnvironmentVariableResponse, CreateEnvironmentVariableResponses, CreateExternalServiceRequest, CreateFlagData, CreateFlagErrors, CreateFlagRequest, CreateFlagResponse, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelRequest, CreateFunnelResponse, CreateFunnelResponse2, CreateFunnelResponses, CreateFunnelStep, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponse, CreateGenericProviderResponses, CreateGenericRequest, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponse, CreateGiteaPatProviderResponses, CreateGiteaPatRequest, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponse, CreateGithubPatProviderResponses, CreateGitHubPatRequest, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponse, CreateGitlabOauthProviderResponses, CreateGitLabOAuthRequest, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponse, CreateGitlabPatProviderResponses, CreateGitLabPatRequest, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponse, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponse, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponse, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentRequest, CreateIncidentResponse, CreateIncidentResponses, CreateIntegrationBody, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlErrors, CreateIpAccessControlRequest, CreateIpAccessControlResponse, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpRequest, CreateMcpResponse, CreateMcpResponses, CreateMetricAlertRequest, CreateMonitorData, CreateMonitorErrors, CreateMonitorRequest, CreateMonitorResponse, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderRequest, CreateNotificationEmailProviderResponse, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponse, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderRequest, CreateOidcProviderResponse, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingRequest, CreateOidcRoleMappingResponse, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponse, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanRequest, CreatePlanResponse, CreatePlanResponse2, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateRequest, CreateProjectFromTemplateResponse, CreateProjectFromTemplateResponse2, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponse, CreateProjectReleaseResponses, CreateProjectRequest, CreateProjectResponse, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretRequest, CreateProjectSecretResponse, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyErrors, CreateProviderKeyRequest, CreateProviderKeyResponse, CreateProviderKeyResponses, CreateProviderRequest, CreatePrResponse, CreatePrResponse2, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponse, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteRequest, CreateRouteResponse, CreateRouteResponses, CreateS3SourceData, CreateS3SourceError, CreateS3SourceErrors, CreateS3SourceRequest, CreateS3SourceResponse, CreateS3SourceResponses, CreateSandboxBody, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponse, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponse, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillRequest, CreateSkillResponse, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderRequest, CreateSlackProviderResponse, CreateSlackProviderResponses, CreateUserData, CreateUserErrors, CreateUserRequest, CreateUserResponse, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderRequest, CreateWebhookProviderResponse, CreateWebhookProviderResponses, CreateWebhookRequestBody, CreateWebhookResponse, CreateWebhookResponses, CronExecutionInfo, CronInfo, CrossProjectSiblingRef, CrossProjectTraceResponse, CurrentStatusResponse, CustomDomainRequest, CustomDomainResponse, CustomerMovementResponse, DashboardLayout, DashboardProjectsAnalyticsQuery, DashboardProjectsAnalyticsResponse, DashboardSection, DashboardTile, DatabaseMetricsResponse, DatabaseMetricsRow, DataImplication, DataImplicationSeverity, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponse, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAlertData, DeleteAlertError, DeleteAlertErrors, DeleteAlertResponse, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponse, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponse, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupError, DeleteBackupErrors, DeleteBackupResponse, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleErrors, DeleteBackupScheduleResponse, DeleteBackupScheduleResponses, DeleteBlobRequest, DeleteBlobResponse, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponse, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponse, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardError, DeleteDashboardErrors, DeleteDashboardResponse, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponse, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponse, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponse, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponse, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponse, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponse, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponse, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponse, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponse, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponse, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponse, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlErrors, DeleteIpAccessControlResponse, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponse, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponse, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponse, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponse, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponse, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyErrors, DeleteProviderKeyResponse, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponse, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponse, DeleteReleaseSourceMapsResponses, DeleteResponse, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponse, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceErrors, DeleteS3SourceResponse, DeleteS3SourceResponses, DeleteScanData, DeleteScanError, DeleteScanErrors, DeleteScanResponse, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponse, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponse, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponse, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponse, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponse, DeleteStaticBundleResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponse, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponse, DeleteWebhookResponses, DelRequest, DelResponse, DeployFromImageData, DeployFromImageErrors, DeployFromImageRequest, DeployFromImageResponse, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadQuery, DeployFromImageUploadResponse, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticRequest, DeployFromStaticResponse, DeployFromStaticResponses, DeploymentConfig, DeploymentConfigSnapshot, DeploymentConfiguration, DeploymentContainerLogContentResponse, DeploymentContainerLogResponse, DeploymentContainerLogsListResponse, DeploymentEnvironmentResponse, DeploymentJobResponse, DeploymentJobsResponse, DeploymentListResponse, DeploymentMetadata, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponse, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DeploymentResponse, DeploymentStateResponse, DeploymentStrategy, DeploymentTokenListResponse, DeploymentTokenResponse, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponse, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceErrors, DetachScheduleServiceResponse, DetachScheduleServiceResponses, DetectionConfig, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponse, DetectPublicPresetsResponses, DeviceCount, DigestSections, Direction, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponse, DisableBackupScheduleResponses, DisableBlobResponse, DisableKvResponse, DisableMfaData, DisableMfaErrors, DisableMfaRequest, DisableMfaResponse, DisableMfaResponses, DiscoverRequest, DiscoverResponse, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponse, DiscoverWorkloadsResponses, DiskInfo, DiskSpaceAlert, DiskSpaceAlertSettings, DiskSpaceCheckResult, DnsAckRequest, DnsAckResponse, DnsChallengeRecordResult, DnsChangesResponse, DnsCompletionResponse, DnsLookupError, DnsLookupRequest, DnsLookupResponse, DnsProviderCredentials, DnsProviderResponse, DnsProviderSettings, DnsProviderSettingsMasked, DnsProviderType, DnsRecord, DnsRecordChange, DnsRecordContent, DnsRecordResponse, DnsRecordSetupResult, DnsRecordStatusResponse, DnsZone, DockerComposePresetConfig, DockerfilePresetConfig, DockerfileVariant, DockerRegistrySettings, DockerRegistrySettingsMasked, DomainAction, DomainChallengeResponse, DomainData, DomainEnvironmentResponse, DomainError, DomainErrors, DomainPlan, DomainResponse, DomainResponse2, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponse, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponse, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponse, DownloadSkillArchiveResponses, DrainNodeResponse, DrainStatusResponse, DropOffPoint, EmailConfig, EmailDomainResponse, EmailDomainWithDnsResponse, EmailProviderResponse, EmailProviderTypeRoute, EmailRequest, EmailResponse, EmailStatsResponse, EmailStatusData, EmailStatusErrors, EmailStatusResponse, EmailStatusResponse2, EmailStatusResponses, EmailTrackingResponse, EmailTrackingSetupResponse, EmailTrackingStatusResponse, EmbeddingData, EmbeddingInput, EmbeddingRequest, EmbeddingResponse, EmbeddingsData, EmbeddingsError, EmbeddingsErrors, EmbeddingsResponse, EmbeddingsResponses, EmbeddingUsage, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponse, EnableBackupScheduleResponses, EnableBlobRequest, EnableBlobResponse, EnableKvRequest, EnableKvResponse, EnablePgStatStatementsResponse, EndpointDto, EnqueuedJob, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorRequest, EnrichVisitorResponse, EnrichVisitorResponse2, EnrichVisitorResponses, EnrollmentTokenInfo, EnrollmentTokenListResponse, EntityInfoResponse, EntityResponse, EnvironmentConfiguration, EnvironmentDomainResponse, EnvironmentInfo, EnvironmentResponse, EnvironmentVariable, EnvironmentVariableInfo, EnvironmentVariableResponse, EnvironmentVariableValueResponse, EnvVarInput, EnvVarIntegrationInfo, EnvVarResponse, EnvVarTemplateResponse, ErrorDashboardStatsQuery, ErrorDashboardStatsResponse, ErrorEventResponse, ErrorGroupResponse, ErrorGroupStatsResponse, ErrorResponse, ErrorRow, ErrorTimeSeriesDataResponse, ErrorTimeSeriesQuery, EventActivityBucket, EventBreakdown, EventBrowserStats, EventCount, EventCountryStats, EventDetailQuery, EventDetailResponse, EventEntriesQuery, EventEntriesResponse, EventEntryInfo, EventKind, EventMetricsPayload, EventReferrerStats, EventsCountQuery, EventsResponse, EventTimeline, EventTimelineQuery, EventType, EventTypeBreakdown, EventTypeBreakdownQuery, EventTypeResponse, EventTypesResponse, EventVisitorInfo, EventVisitorsQuery, EventVisitorsResponse, ExecBody, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponse, ExecDetachedResponse2, ExecDetachedResponses, ExecErrors, ExecResponse, ExecResponse2, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponse, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportRequest, ExecuteImportResponse, ExecuteImportResponse2, ExecuteImportResponses, ExecuteOperationRequest, ExpireRequest, ExpireResponse, ExplorerSupportResponse, ExtendTimeoutBody, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponse, ExtendTimeoutResponses, ExternalImageResponse, ExternalServiceBackupResponse, ExternalServiceDetails, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceInfo, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceSummary, FieldResponse, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponse, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponse, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponse, FindConversationResponses, FiringSeriesEntry, FlagEnvironmentResponse, FlagListResponse, FlagResponse, FlagSnapshot, FlagSnapshotResponse, FlagValueType, ForecastAlgorithm, ForecastParams, FullError, FullEvent, FullRequest, FunnelMetricsResponse, FunnelResponse, GatewayStatus, GenAiEvent, GenAiSpanDetail, GenAiTraceDetailResponse, GenAiTraceSummariesResponse, GenAiTraceSummary, GeneralStatsQuery, GeneralStatsResponse, GenerateDockerfileRequest, GenerateDockerfileResponse, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponse, GenerateJoinTokenResponse2, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponse, GeneratePresetDockerfileResponses, GeoLocationResponse, GeoRestrictionsConfig, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponse, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponse, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponse, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponse, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponse, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponse, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesErrors, GetAiAgentPagesResponse, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineErrors, GetAiAgentTimelineResponse, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownErrors, GetAiPageBreakdownResponse, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponse, GetAiStatusBreakdownResponses, GetAlertData, GetAlertError, GetAlertErrors, GetAlertResponse, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponse, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponse, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponse, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponse, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponse, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponse, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponse, GetApiKeyPermissionsResponses, GetApiKeyResponse, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponse, GetAuditLogResponses, GetBackupData, GetBackupError, GetBackupErrors, GetBackupResponse, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponse, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponse, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponse, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponse, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponse, GetChallengeTokenResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponse, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponse, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponse, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponse, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponse, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponse, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponse, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailErrors, GetConversationDetailResponse, GetConversationDetailResponses, GetConversationErrors, GetConversationResponse, GetConversationResponses, GetConversationsData, GetConversationsError, GetConversationsErrors, GetConversationsResponse, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponse, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponse, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponse, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponse, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponse, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponse, GetCustomDomainResponses, GetDashboardData, GetDashboardError, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponse, GetDashboardProjectsAnalyticsResponses, GetDashboardResponse, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponse, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponse, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponse, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponse, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponse, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponse, GetDeploymentOperationStatusResponses, GetDeploymentResponse, GetDeploymentResponses, GetDeploymentsParams, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponse, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponse, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponse, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponse, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponse, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponse, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponse, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponse, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponse, GetDomainOrderResponses, GetDomainResponse, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponse, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponse, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponse, GetEmailProviderResponses, GetEmailResponse, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponse, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponse, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponse, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponse, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponse, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponse, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponse, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponse, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesQuery, GetEnvironmentVariablesResponse, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponse, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponse, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponse, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponse, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponse, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponse, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponse, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponse, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponse, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponse, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponse, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponse, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponse, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponse, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponse, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponse, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsQuery, GetFunnelMetricsResponse, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceErrors, GetGenaiTraceResponse, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponse, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponse, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponse, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponse, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponse, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponse, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponse, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponse, GetGroupedPageMetricsResponses, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponse, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponse, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponse, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponse, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponse, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlErrors, GetIpAccessControlResponse, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationErrors, GetIpGeolocationResponse, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponse, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponse, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanError, GetLatestScanErrors, GetLatestScanResponse, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponse, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponse, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextError, GetLogContextErrors, GetLogContextResponse, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponse, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeErrors, GetMetricsOverTimeResponse, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponse, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponse, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponse, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnRequest, GetOrCreateDsnResponse, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponse, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponse, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponse, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponse, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponse, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponse, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponse, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsErrors, GetPerformanceMetricsResponse, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponse, GetPgUpgradeLogsResponses, GetPgUpgradeResponse, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsErrors, GetPipelineStatsResponse, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponse, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponse, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponse, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingError, GetPricingErrors, GetPricingResponse, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponse, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponse, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponse, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponse, GetProjectResponses, GetProjectsData, GetProjectSecretsQuery, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponse, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysErrors, GetProjectSessionReplaysQuery, GetProjectSessionReplaysResponse, GetProjectSessionReplaysResponse2, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthErrors, GetProjectsHealthResponse, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponse, GetProjectsMonitorHealthResponses, GetProjectsResponse, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponse, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponse, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponse, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponse, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponse, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponse, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponse, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdErrors, GetProxyLogByIdResponse, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponse, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsError, GetProxyLogsErrors, GetProxyLogsResponse, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponse, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponse, GetPublicRepositoryResponses, GetQuotaData, GetQuotaError, GetQuotaErrors, GetQuotaResponse, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponse, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponse, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponse, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponse, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponse, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponse, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponse, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponse, GetRepositoryTagsResponses, GetRequest, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponse, GetResolvedEnvironmentVariableValueResponses, GetResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponse, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunError, GetRestoreRunErrors, GetRestoreRunResponse, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponse, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponse, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponse, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponse, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceError, GetS3SourceErrors, GetS3SourceResponse, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponse, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponse, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentErrors, GetScanByDeploymentResponse, GetScanByDeploymentResponses, GetScanData, GetScanError, GetScanErrors, GetScanResponse, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponse, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponse, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponse, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponse, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponse, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponse, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponse, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponse, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponse, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponse, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponse, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayError, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsErrors, GetSessionReplayEventsResponse, GetSessionReplayEventsResponses, GetSessionReplayResponse, GetSessionReplayResponse2, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponse, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponse, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponse, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponse, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponse, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponse, GetTagsByRepositoryIdResponses, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsErrors, GetTimeBucketStatsResponse, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsError, GetTodayStatsErrors, GetTodayStatsResponse, GetTodayStatsResponses, GetTraceData, GetTraceError, GetTraceErrors, GetTraceResponse, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceErrors, GetUnifiedTraceResponse, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponse, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsQuery, GetUniqueEventsResponse, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponse, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponse, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderErrors, GetUsageByProviderResponse, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentError, GetUsageRecentErrors, GetUsageRecentResponse, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryErrors, GetUsageSummaryResponse, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesErrors, GetUsageTimeseriesResponse, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsErrors, GetUsageTopModelsResponse, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponse, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponse, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponse, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponse, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponse, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponse, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsErrors, GetVisitorSessionsQuery, GetVisitorSessionsResponse, GetVisitorSessionsResponse2, GetVisitorSessionsResponses, GetVisitorsResponse, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponse, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponse, GetWebhookResponses, GitPushEvent, GitRefResponse, GitSourcePlan, GlobalConversationResponse, GlobalEventStatsResponse, GlobalMrrResponse, GlobalRecentEventResponse, GlobalRevenueSummaryResponse, GroupedPageMetric, GroupedPageMetricsQuery, GroupedPageMetricsResponse, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponse, HasAnalyticsEventsResponse2, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponse, HasErrorGroupsResponse2, HasErrorGroupsResponses, HasEventsQuery, HasEventsResponse, HasMetricsQuery, HasMetricsResponse, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsErrors, HasPerformanceMetricsResponse, HasPerformanceMetricsResponses, HealthCheckConfiguration, HealthCheckEntryResponse, HealthResponse, HealthStatus, HealthSummary, HeartbeatApiRequest, HeartbeatResponse, HierarchyLevel, HistogramSummary, HostnameChange, HostnamePreviewResponse, HourlyPageSessions, HourlyVisitsQuery, HttpChallengeDebugResponse, ImportCredentials, ImportExecutionStatus, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceRequest, ImportExternalServiceResponse, ImportExternalServiceResponses, ImportOutcomeResponse, ImportPlan, ImportRowErrorResponse, ImportSelector, ImportSource, ImportSourceCapabilities, ImportSourceInfo, ImportStatusResponse, IncidentBucket, IncidentBucketedResponse, IncidentResponse, IncidentUpdateResponse, IncrRequest, IncrResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsError, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsError, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponse, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathError, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesError, IngestTracesErrors, IngestTracesResponses, InitAuthResponse, InitSessionReplayData, InitSessionReplayError, InitSessionReplayErrors, InitSessionReplayResponse, InitSessionReplayResponses, Insight, InsightSeverity, InsightsResponse, InsightStatus, IntegrationResponse, IpAccessControlQuery, IpAccessControlResponse, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponse, JobStatusResponse2, JobStatusResponses, JobSummaryResponse, JoinTokenStatusResponse, JourneyEvent, JourneySession, KeysRequest, KeysResponse, KillJobBody, KillJobData, KillJobErrors, KillJobResponse, KillJobResponses, KnownAiAgentsResponse, KvDelData, KvDelErrors, KvDelResponse, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponse, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponse, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponse, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponse, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponse, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponse, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponse, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponse, KvStatusResponse2, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponse, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponse, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponse, LatestRunForSourceResponses, LemonSqueezyConfig, LetsEncryptSettings, LineContext, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponse, LinkCustomDomainToCertificateResponses, LinkServiceRequest, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponse, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponse, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponse, ListAgentsResponse2, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponse, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponse, ListAlertRulesResponses, ListAlertsData, ListAlertsError, ListAlertsErrors, ListAlertsResponse, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponse, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponse, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysQuery, ListApiKeysResponse, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsQuery, ListAuditLogsResponse, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponse, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsErrors, ListBackupAlertsResponse, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenErrors, ListBackupChildrenResponse, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesErrors, ListBackupSchedulesResponse, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponse, ListBackupsForScheduleResponses, ListBlobsQuery, ListBlobsResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponse, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponse, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponse, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponse, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponse, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponse, ListCustomDomainsForProjectResponses, ListCustomDomainsResponse, ListDashboardsData, ListDashboardsError, ListDashboardsErrors, ListDashboardsResponse, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponse, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensQuery, ListDeploymentTokensResponse, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponse, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponse, ListDomainsResponse2, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponse, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponse, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponse, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponse, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesQuery, ListEntitiesResponse, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsQuery, ListErrorEventsResponse, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsQuery, ListErrorGroupsResponse, ListErrorGroupsResponses, ListEventsData, ListEventsResponse, ListEventsResponses, ListEventTypesData, ListEventTypesResponse, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponse, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponse, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponse, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponse, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponse, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponse, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponse, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponse, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsError, ListInsightsErrors, ListInsightsResponse, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlErrors, ListIpAccessControlResponse, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponse, ListJobsResponse2, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsErrors, ListKnownAiAgentsResponse, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponse, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponse, ListMcpsResponse2, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysErrors, ListMetricLabelKeysResponse, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesErrors, ListMetricLabelValuesResponse, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesError, ListMetricNamesErrors, ListMetricNamesResponse, ListMetricNamesResponses, ListModelsData, ListModelsError, ListModelsErrors, ListModelsResponse, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponse, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponse, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponse, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponse, ListOnDemandCertsResponse2, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponse, ListOrdersResponse2, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponse, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponse, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponse, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponse, ListPresetsResponse2, ListPresetsResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponse, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansError, ListProjectScansErrors, ListProjectScansResponse, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponse, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponse, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponse, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponse, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysError, ListProviderKeysErrors, ListProviderKeysResponse, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponse, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponse, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponse, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponse, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponse, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponse, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponse, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponse, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponse, ListRoutesResponses, ListRunsResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesErrors, ListS3SourcesResponse, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponse, ListSandboxesResponse2, ListSandboxesResponses, ListScansQuery, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsErrors, ListScheduleRunJobsResponse, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsErrors, ListScheduleRunsResponse, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesErrors, ListScheduleServicesResponse, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponse, ListSecretsResponse2, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponse, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponse, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesErrors, ListServiceSchedulesResponse, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponse, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponse, ListSkillsResponse2, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsErrors, ListSourceBackupsResponse, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponse, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponse, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponse, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponse, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponse, ListSyncedRepositoriesResponses, ListTagsResponse, ListTemplatesQuery, ListTemplatesResponse, ListUsersData, ListUsersErrors, ListUsersResponse, ListUsersResponses, ListVulnerabilitiesQuery, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponse, ListWebhooksResponses, LiveVisitorInfo, LiveVisitorsListResponse, LocationCount, LocationGranularity, LocationInfo, LoginData, LoginErrors, LoginRequest, LoginResponse, LoginResponses, LogLevel, LogoutData, LogoutErrors, LogoutResponses, LogRecord, LogSearchLine, LogSeverity, LogSource, LogsQuery, LogsResponse, LogStream, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsErrors, LookupDnsARecordsResponse, LookupDnsARecordsResponses, ManagedDomainResponse, ManualAction, ManualActionTiming, McpDefinitionResponse, MessageContent, MessagePart, MessageResponse, MeteredMode, MetricAggregation, MetricBucket, MetricDataPoint, MetricsOverTimeResponse, MetricsQuery, MetricsRangeQuery, MetricsStatusResponse, MetricsStoreKind, MetricsSummaryResponse, MetricType, MfaRequiredResponse, MfaSetupResponse, MfaVerificationRequest, MigrationStep, MigrationSummary, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenRequest, MintEnrollmentTokenResponse, MintEnrollmentTokenResponse2, MintEnrollmentTokenResponses, MiscResult, MkdirBody, MkdirData, MkdirErrors, MkdirResponse, MkdirResponses, ModelInfo, ModelListResponse, ModelPricing, ModelUsage, MonitoringSettings, MonitoringSettingsMasked, MonitorResponse, MonitorStatus, MrrBucketResponse, MultiNodeSettings, MultiNodeSettingsMasked, MxResult, NavEntry, NavSection, NetworkConfiguration, NetworkMode, NixpacksPresetConfig, NixpacksProvider, NodeContainerListResponse, NodeContainerResponse, NodeCostInfo, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponse, NodeHeartbeatResponses, NodeInfoResponse, NodeListResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponse, NodeMetricsGetRangeResponses, NotificationPreferencesResponse, NotificationProviderResponse, ObservabilityCompressionSettings, ObservabilityEvent, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventErrors, ObservabilityFullEventResponse, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsErrors, ObservabilityListEventsResponse, ObservabilityListEventsResponses, ObservabilityRetentionSettings, OidcCallbackData, OidcProviderResponse, OidcProvidersListResponse, OidcProviderSummary, OidcProviderUserResponse, OidcRoleMappingResponse, OidcTestConnectionResponse, OnDemandCertAttemptResponse, OnDemandCertRow, OnDemandTlsSettings, OpenAiError, OpenAiErrorResponse, OperatingSystemCount, OperationResultResponse, OperationResultsResponse, OtelDashboardResponse, OtelDashboardsResponse, OtelMetricAlertRuleResponse, OtelMetricAlertsResponse, OtelMetricLabelKeysResponse, OtelMetricLabelValuesResponse, OtelMetricNamesResponse, OtelMetricsResponse, OutlierAlgorithm, OutlierParams, OverprovisioningAssessment, OverprovisioningVerdict, PageActivityBucket, PageCountryStats, PageFlowEntry, PageFlowQuery, PageFlowResponse, PageHourlySessionsQuery, PageHourlySessionsResponse, PagePathDetailQuery, PagePathDetailResponse, PagePathInfo, PagePathSparkline, PagePathSparklinePoint, PagePathsQuery, PagePathsResponse, PagePathsSparklineQuery, PagePathsSparklineResponse, PagePathVisitorsQuery, PagePathVisitorsResponse, PageReferrerStats, PagesComparisonResponse, PageSessionComparison, PageSessionStats, PageSessionStatsQuery, PageTransition, PageVisit, PageVisitorSession, PaginatedEmailsResponse, PaginatedEntitiesResponse, PaginatedErrorEventsResponse, PaginatedErrorGroupsResponse, PaginatedEventsResponse, PaginatedExternalImagesResponse, PaginatedProjectList, PaginatedStaticBundlesResponse, Pagination, PaginationMeta, PaginationParams, PasswordProtectionConfig, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponse, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PatchPreviewGatewaySettingsResponses, PatchSettingsRequest, PathVisitors, PathVisitorsAnalyticsQuery, PathVisitorsResponse, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponse, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponse, PauseSandboxResponses, PeerEntry, PeerListResponse, PendingActionResponse, PerformanceMetricsQuery, PerformanceMetricsResponse, PermissionInfo, PgUpgradeLogResponse, PgUpgradeResponse, PipelineStats, PipelineStatsResponse, PlanComplexity, PlanMetadata, PlanRestoreData, PlanRestoreError, PlanRestoreErrors, PlanRestoreResponse, PlanRestoreResponses, PlanSourceBackup, PlanTarget, PlatformInfo, PluginManifest, PortMapping, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponse, PostDnsAckResponses, PostgresWalHealth, PresetConfigSchema, PresetInfo, PresetResponse, PreviewAlertData, PreviewAlertError, PreviewAlertErrors, PreviewAlertResponse, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponse, PreviewFunnelMetricsResponses, PreviewGatewaySettings, PreviewGatewaySettingsMasked, PreviewGatewaySettingsResponse, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponse, PreviewHostnameModeResponses, PricingResponse, ProblemDetails, ProjectConfiguration, ProjectDashboardAnalytics, ProjectDsnResponse, ProjectHealthSummary, ProjectInfo, ProjectMonitorHealth, ProjectPresetResponse, ProjectQuery, ProjectRef, ProjectResponse, ProjectSecretEnvironmentInfo, ProjectSecretResponse, ProjectServiceInfo, ProjectsHealthResponse, ProjectsMonitorHealthResponse, ProjectStatisticsResponse, ProjectStatsBreakdown, ProjectType, ProjectUsageInfoResponse, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentRequest, PromoteDeploymentResponse, PromoteDeploymentResponses, PropertyBreakdownItem, PropertyBreakdownQuery, PropertyBreakdownResponse, PropertyColumn, PropertyTimelineItem, PropertyTimelineQuery, PropertyTimelineResponse, Protocol, ProviderCatalogDto, ProviderCatalogResponse, ProviderConfig, ProviderConfigMasked, ProviderDeletionCheckResponse, ProviderDescriptor, ProviderKeyResponse, ProviderMetadata, ProviderResponse, ProviderUsage, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponse, ProvisionDomainResponses, ProvisionResponse, ProxyLogResponse, ProxyLogsPaginatedResponse, ProxyRequest, PublicHostnameStrategy, PublicPresetResponse, PublicRepositoryInfo, PurgeLogsRequest, PurgeProjectLogsData, PurgeProjectLogsError, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushedExternalImageResponse, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponse, PushExternalImageResponses, PushImageRequest, QueryDataData, QueryDataErrors, QueryDataRequest, QueryDataResponse, QueryDataResponse2, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesErrors, QueryGenaiTracesResponse, QueryGenaiTracesResponses, QueryLogsData, QueryLogsError, QueryLogsErrors, QueryLogsResponse, QueryLogsResponses, QueryMetricsData, QueryMetricsError, QueryMetricsErrors, QueryMetricsResponse, QueryMetricsResponses, QueryTracesData, QueryTracesError, QueryTracesErrors, QueryTracesResponse, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesErrors, QueryTraceSummariesResponse, QueryTraceSummariesResponses, QuotaResponse, RateLimitConfig, RateLimitSettings, ReachabilityStatus, ReadFileData, ReadFileErrors, ReadFileResponse, ReadFileResponse2, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RecentActivityQuery, RecentActivityResponse, RecentEventResponse, RecentQueryParams, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponse, RecordEventMetricsResponses, RecordListResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsErrors, RecordSpeedMetricsResponse, RecordSpeedMetricsResponses, RecoveryTarget, ReferrerCount, ReferrersAnalyticsQuery, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponse, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnRequest, RegenerateDsnResponse, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponse, RegisterExternalImageResponses, RegisterImageRequest, RegisterNodeApiRequest, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponse, RegisterNodeResponse2, RegisterNodeResponses, RegisterRequest, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponse, ReinstallGitlabWebhookResponses, ReinstallWebhookResponse, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponse, RejectPendingActionResponses, ReleaseListResponse, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponse, ReloadPluginsResponses, ReloadResponse, RemoteDeploymentResponse, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponse, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponse, RemoveManagedDomainResponses, RemoveNodeResponse, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponse, RemoveRoleResponses, RenameConversationData, RenameConversationErrors, RenameConversationRequest, RenameConversationResponse, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponse, RenewDomainResponses, RepositoryListQuery, RepositoryListResponse, RepositoryPresetResponse, RepositoryResponse, RepositorySyncStartedResponse, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponse, RequestPasswordResetResponses, RequestRow, ResetPasswordData, ResetPasswordErrors, ResetPasswordRequest, ResetPasswordResponse, ResetPasswordResponses, ResizeSandboxBody, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponse, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, ResolvedEnvVarResponse, ResolvedEnvVarSource, ResourceCounts, ResourceFootprint, ResourceInfo, ResourceLimitApplyResult, ResourceLimits, ResourceLimitsResponse, ResourceLimitsUpdateResponse, ResourcesBody, RestartContainerData, RestartContainerErrors, RestartContainerResponse, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponse, RestartSandboxResponses, RestoreCapabilities, RestoreCapabilitiesResponse, RestorePlan, RestoreRequestMode, RestoreRunView, RestoreUserData, RestoreUserErrors, RestoreUserResponse, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponse, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponse, ResumeSandboxResponses, RetentionCleanupFailure, RetentionCleanupReport, RetryClusterData, RetryClusterErrors, RetryClusterRequest, RetryClusterResponse, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponse, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponse, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponse, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponse, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponse, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponse, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponse, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponse, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponse, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponse, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponse, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueRotateTokenResponses, RevenueRow, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponse, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponse, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponse, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponse, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponse, RevokeJoinTokenResponses, RiskLevel, RoleInfo, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponse, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponse, RollbackToDeploymentResponses, RootfsCacheEntry, RootfsGcData, RootfsGcReport, RootfsGcResponses, RootfsReport, RootfsReportData, RootfsReportResponses, RootfsVmEntry, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponse, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponse, RotateDeploymentTokenResponses, RouteRefreshResponse, RouteResponse, RouteRole, RouteUser, RouteUserWithRoles, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceErrors, RunBackupForSourceResponse, RunBackupForSourceResponses, RunBackupRequest, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponse, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupErrors, RunExternalServiceBackupRequest, RunExternalServiceBackupResponse, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowError, RunScheduleNowErrors, RunScheduleNowResponse, RunScheduleNowResponses, S3ConnectionTestResponse, S3CredentialsResponse, S3SourceResponse, S3SourceResponseWritable, SandboxDomainResponse, SandboxEvent, SandboxEventsResponse, SandboxInner, SandboxResponse, SandboxRoute, SandboxStatusResponse, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenRequest, SaveAgentTokenResponse, SaveAgentTokenResponse2, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponse, SaveAiProviderCredentialResponses, SaveCredentialRequest, SaveCredentialResponse, ScalewayCredentialsRequest, ScanResponse, ScheduleRunEntry, ScheduleRunJobEntry, ScheduleRunListResponse, ScheduleRunResponse, ScheduleRunSummary, ScheduleRunSummaryList, ScreenshotSettings, SearchLogsData, SearchLogsError, SearchLogsErrors, SearchLogsRequest, SearchLogsResponse, SearchLogsResponse2, SearchLogsResponses, SearchMode, Seasonality, SecretResponse, SecurityConfig, SecurityHeadersConfig, SecurityHeadersSettings, SendEmailData, SendEmailErrors, SendEmailRequestBody, SendEmailResponse, SendEmailResponseBody, SendEmailResponses, SendMessageRequest, SensitiveConfigValueResponse, SensitiveMcpConfigValueResponse, SensitiveValueResponse, SentryChunkUploadResponse, SentryCreateReleaseRequest, SentryEventRequest, SentryEventResponse, SentryReleaseFileResponse, SentryReleaseProjectRef, SentryReleaseResponse, SeriesStateEntry, ServiceAccessInfo, ServiceAction, ServiceAlertRuleResponse, ServiceBackupEntryResponse, ServiceBackupListResponse, ServiceCreateAlertRuleRequest, ServiceHealthResponse, ServiceHealthStatusBatchResponse, ServiceHealthStatusEntryResponse, ServiceMemberInfo, ServiceParameter, ServicePlan, ServiceResourceLimits, ServiceRuntimeReport, ServiceStatsReport, ServiceTypeInfo, ServiceTypeRoute, ServiceUpdateAlertRuleRequest, SesCredentialsRequest, SessionDetails, SessionDetailsQuery, SessionEvent, SessionEventDto, SessionEventsQuery, SessionEventsResponse, SessionLogsQuery, SessionLogsResponse, SessionReplayEventsRequest, SessionReplayInfoDto, SessionReplayInitRequest, SessionReplayInitResponse, SessionReplayWithEventsDto, SessionReplayWithVisitorDto, SessionRequestLog, SessionSummary, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceErrors, SetDefaultS3SourceResponse, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentRequest, SetFlagEnvironmentResponse, SetFlagEnvironmentResponses, SetPreviewPasswordBody, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponse, SetPreviewPasswordResponse2, SetPreviewPasswordResponses, SetRequest, SetResponse, SettingsUpdateResponse, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeRequest, SetupDnsChallengeResponse, SetupDnsChallengeResponse2, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsRequest, SetupDnsResponse, SetupDnsResponse2, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponse, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponse, SetupMfaResponses, SiblingRef, SkillDefinitionResponse, SlackConfig, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponse, SleepEnvironmentResponses, SlowQueriesResponse, SlowQueryRow, SmartFilter, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponse, SmokeTestAgentResponses, SmokeTestResponse, SmtpCredentialsRequest, SmtpEncryptionRoute, SmtpResult, SourceBackupEntry, SourceBackupIndexResponse, SourceBody, SourceFileListResponse, SourceFileResponse, SourceMapListResponse, SourceMapResponse, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponse, SourceSandboxResponses, SourceType, SpanEvent, SpanKind, SpanRecord, SpanRow, SpanStatusCode, SpeedMetricsPayload, SpeedSegmentFilters, StaleSlot, StartAnalysisData, StartAnalysisErrors, StartAnalysisRequest, StartAnalysisResponse, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponse, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeRequest, StartPgUpgradeResponse, StartPgUpgradeResponses, StartRestoreData, StartRestoreError, StartRestoreErrors, StartRestoreRequest, StartRestoreResponse, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponse, StartServiceResponses, StaticBundleResponse, StaticParams, StaticPresetConfig, StatPathData, StatPathErrors, StatPathResponse, StatPathResponses, StatResponse, StatsFilters, StatusBucket, StatusBucketedResponse, StatusCodeCount, StatusCodesQuery, StatusPageOverview, StepConversionResponse, StepResourceType, StepResult, StopContainerData, StopContainerErrors, StopContainerResponse, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponse, StopSandboxResponses, StopSequence, StopServiceData, StopServiceErrors, StopServiceResponse, StopServiceResponses, StorageQuota, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, StripeConfig, SyncedRepositoryListQuery, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponse, SyncRepositoriesResponses, SyntaxResult, TagInfo, TagListResponse, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsError, TailLogsErrors, TailLogsRequest, TailLogsResponses, TargetRecommendation, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponse, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponse, TeardownEnvironmentResponses, TemplateResponse, TestEmailRequest, TestEmailResponse, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponse, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponse, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponse, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdErrors, TestProviderKeyByIdResponse, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineErrors, TestProviderKeyInlineResponse, TestProviderKeyInlineResponses, TestProviderKeyRequest, TestProviderKeyResponse, TestProviderResponse, TestProviderResponse2, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponse, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionErrors, TestS3SourceConnectionResponse, TestS3SourceConnectionResponses, TimeBucketStats, TimeBucketStatsResponse, TimeseriesBucket, TimeseriesQueryParams, TlsMode, TodayStatsResponse, ToggleDeploymentMetricsRequest, ToggleServiceMetricsRequest, TokenRenewalRequest, ToolCallEvent, ToolInfo, ToolResultEvent, TopModelsQueryParams, TraceProjectRef, TracesResponse, TraceSummariesResponse, TraceSummary, TrackClickData, TrackClickErrors, TrackedLinkResponse, TrackingEventResponse, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentRequest, TriggerAgentResponse, TriggerAgentResponses, TriggerDigestResponse, TriggerPipelinePayload, TriggerPipelineResponse, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponse, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanError, TriggerScanErrors, TriggerScanRequest, TriggerScanResponse, TriggerScanResponse2, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponse, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponse, TriggerWeeklyDigestResponses, TtlRequest, TtlResponse, TxtRecord, UiManifest, UiRoute, UndrainNodeResponse, UnifiedTrace, UniqueCountsQuery, UniqueCountsResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponse, UnlinkServiceFromProjectResponses, UnsupportedFeature, UpdateAdminGateRequest, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderRequest, UpdateAiProviderResponse, UpdateAiProviderResponse2, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertError, UpdateAlertErrors, UpdateAlertResponse, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleRequest, UpdateAlertRuleResponse, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyRequest, UpdateApiKeyResponse, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployRequest, UpdateAutomaticDeployResponse, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleErrors, UpdateBackupScheduleRequest, UpdateBackupScheduleResponse, UpdateBackupScheduleResponses, UpdateBlobRequest, UpdateBlobResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderRequest, UpdateCloudflareProviderResponse, UpdateCloudflareProviderResponses, UpdateConfigBody, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponse, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainRequest, UpdateCustomDomainResponse, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardError, UpdateDashboardErrors, UpdateDashboardRequest, UpdateDashboardResponse, UpdateDashboardResponses, UpdateDeploymentConfigRequest, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenRequest, UpdateDeploymentTokenResponse, UpdateDeploymentTokenResponses, UpdateDnsProviderRequest, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderRequest, UpdateEmailProviderResponse, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsRequest, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainRequest, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableRequest, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupRequest, UpdateErrorGroupResponses, UpdateExternalServiceRequest, UpdateFlagData, UpdateFlagErrors, UpdateFlagRequest, UpdateFlagResponse, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponse, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsRequest, UpdateGitSettingsResponse, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponse, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponse, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusRequest, UpdateIncidentStatusResponse, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlErrors, UpdateIpAccessControlRequest, UpdateIpAccessControlResponse, UpdateIpAccessControlResponses, UpdateKvRequest, UpdateKvResponse, UpdateManagedDomainApiRequest, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponse, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpRequest, UpdateMcpResponse, UpdateMcpResponses, UpdateMetricAlertRequest, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderRequest, UpdateNotificationEmailProviderResponse, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponse, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderRequest, UpdateOidcProviderResponse, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesRequest, UpdatePreferencesResponse, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponse, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretRequest, UpdateProjectSecretResponse, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsRequest, UpdateProjectSettingsResponse, UpdateProjectSettingsResponses, UpdateProviderCredentialsRequest, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyErrors, UpdateProviderKeyRequest, UpdateProviderKeyResponse, UpdateProviderKeyResponses, UpdateProviderRequest, UpdateProviderResponse, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteRequest, UpdateRouteResponse, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceErrors, UpdateS3SourceRequest, UpdateS3SourceResponse, UpdateS3SourceResponses, UpdateSecretBody, UpdateSelfData, UpdateSelfErrors, UpdateSelfRequest, UpdateSelfResponse, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponse, UpdateServiceResourcesResponses, UpdateServiceResponse, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationErrors, UpdateSessionDurationRequest, UpdateSessionDurationResponse, UpdateSessionDurationResponse2, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponse, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillRequest, UpdateSkillResponse, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderRequest, UpdateSlackProviderResponse, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsErrors, UpdateSpeedMetricsPayload, UpdateSpeedMetricsResponse, UpdateSpeedMetricsResponses, UpdateStatusResponse, UpdateTokenRequest, UpdateTokenResponse, UpdateUserData, UpdateUserErrors, UpdateUserRequest, UpdateUserResponse, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderRequest, UpdateWebhookProviderResponse, UpdateWebhookProviderResponses, UpdateWebhookRequestBody, UpdateWebhookResponse, UpdateWebhookResponses, UpgradeExternalServiceRequest, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradePreviewGatewayResponses, UpgradeRequest, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponse, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponse, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponse, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponse, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponse, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponse, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponse, UploadStaticBundleResponses, UpsertAgentRequest, UpsertSecretData, UpsertSecretErrors, UpsertSecretRequest, UpsertSecretResponse, UpsertSecretResponses, UptimeDataPoint, UptimeHistoryResponse, UsageFilter, UsageInfo, UsageLogEntry, UsageLogPage, UsageQueryParams, UsageSource, UsageSummary, UserResponse, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponse, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailRequest, ValidateEmailResponse, ValidateEmailResponse2, ValidateEmailResponses, ValidationLevel, ValidationReport, ValidationResponse, ValidationResult, ValidationStatus, ValidationSummary, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponse, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponse, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponse, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponse, VerifyMfaChallengeResponses, VerifyMfaRequest, ViewItem, ViewsOverTime, ViewsOverTimeQuery, VisitorDetails, VisitorFacets, VisitorFacetsQuery, VisitorFacetValue, VisitorInfo, VisitorJourneyQuery, VisitorJourneyResponse, VisitorLocationsQuery, VisitorRecord, VisitorSegmentFilters, VisitorSessionsQuery, VisitorSessionsResponse, VisitorsListQuery, VisitorsResponse, VisitorStats, VisitorWithGeolocation, VolumeMount, VolumeType, VulnerabilityResponse, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponse, WakeEnvironmentResponses, WalWarning, WalWarningSeverity, WebhookConfig, WebhookDeliveryResponse, WebhookResponse, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerRequest, WebhookTriggerResponse, WebhookTriggerResponse2, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunRequest, WorkflowDryRunResponse, WorkflowDryRunResponses, WorkloadDescriptor, WorkloadId, WorkloadStatus, WorkloadType, WriteFileBody, WriteFileData, WriteFileErrors, WriteFileResponse, WriteFileResponses, WriteFilesBody, WriteFilesData, WriteFilesErrors, WriteFilesResponse, WriteFilesResponse2, WriteFilesResponses, ZoneListResponse } from './types.gen'; diff --git a/web/src/api/client/sdk.gen.ts b/web/src/api/client/sdk.gen.ts index a643f2645..09038e013 100644 --- a/web/src/api/client/sdk.gen.ts +++ b/web/src/api/client/sdk.gen.ts @@ -2,7 +2,7 @@ import { type Client, type ClientMeta, formDataBodySerializer, type Options as Options2, type RequestResult, type ServerSentEventsResult, type TDataShape } from './client'; import { client } from './client.gen'; -import type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponses, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainResponses, AddEventsData, AddEventsErrors, AddEventsResponses, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsErrors, AddSessionReplayEventsResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponses, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponses, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeResponses, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponses, AssignRoleData, AssignRoleErrors, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesErrors, AttachScheduleServicesResponses, BlobCopyData, BlobCopyErrors, BlobCopyResponses, BlobDeleteData, BlobDeleteErrors, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponses, BlobDownloadData, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponses, BlobHeadData, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListErrors, BlobListResponses, BlobPutData, BlobPutErrors, BlobPutResponses, BlobStatusData, BlobStatusErrors, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponses, CancelBackupData, CancelBackupErrors, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunErrors, CancelScheduleRunResponses, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceResponses, ChatCompletionsData, ChatCompletionsErrors, ChatCompletionsResponses, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponses, ChunkUploadOptionsData, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsErrors, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartResponses, CliLogoutData, CliLogoutErrors, CliLogoutResponses, CmdData, CmdErrors, CmdKillData, CmdKillErrors, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponses, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponses, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponses, CreateAgentData, CreateAgentErrors, CreateAgentResponses, CreateAlertData, CreateAlertErrors, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleErrors, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponses, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardErrors, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainResponses, CreateDsnData, CreateDsnErrors, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelResponses, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponses, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponses, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponses, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponses, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponses, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentResponses, CreateIpAccessControlData, CreateIpAccessControlErrors, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpResponses, CreateMonitorData, CreateMonitorErrors, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponses, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyErrors, CreateProviderKeyResponses, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteResponses, CreateS3SourceData, CreateS3SourceErrors, CreateS3SourceResponses, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderResponses, CreateUserData, CreateUserErrors, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderResponses, CreateWebhookResponses, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponses, DeleteAlertData, DeleteAlertErrors, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupErrors, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleErrors, DeleteBackupScheduleResponses, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardErrors, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlErrors, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyErrors, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponses, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceErrors, DeleteS3SourceResponses, DeleteScanData, DeleteScanErrors, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponses, DeployFromImageData, DeployFromImageErrors, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticResponses, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceErrors, DetachScheduleServiceResponses, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponses, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponses, DisableMfaData, DisableMfaErrors, DisableMfaResponses, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponses, DomainData, DomainErrors, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponses, EmailStatusData, EmailStatusErrors, EmailStatusResponses, EmbeddingsData, EmbeddingsErrors, EmbeddingsResponses, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponses, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorResponses, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponses, ExecErrors, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportResponses, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponses, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponses, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponses, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponses, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesErrors, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineErrors, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownErrors, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponses, GetAlertData, GetAlertErrors, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponses, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponses, GetBackupData, GetBackupErrors, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailErrors, GetConversationDetailResponses, GetConversationErrors, GetConversationResponses, GetConversationsData, GetConversationsErrors, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponses, GetDashboardData, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponses, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponses, GetDeploymentResponses, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponses, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponses, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceErrors, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponses, GetHealthData, GetHealthErrors, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlErrors, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationErrors, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanErrors, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextErrors, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeErrors, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsErrors, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponses, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsErrors, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingErrors, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponses, GetProjectsData, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysErrors, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthErrors, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponses, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdErrors, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsErrors, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponses, GetQuotaData, GetQuotaErrors, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponses, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponses, GetRestoreCapabilitiesData, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunErrors, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceErrors, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentErrors, GetScanByDeploymentResponses, GetScanData, GetScanErrors, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsErrors, GetSessionReplayEventsResponses, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponses, GetTimeBucketStatsData, GetTimeBucketStatsErrors, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsErrors, GetTodayStatsResponses, GetTraceData, GetTraceErrors, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceErrors, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderErrors, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentErrors, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryErrors, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesErrors, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsErrors, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsErrors, GetVisitorSessionsResponses, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponses, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponses, HasPerformanceMetricsData, HasPerformanceMetricsErrors, HasPerformanceMetricsResponses, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceResponses, IngestLogsByPathData, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesErrors, IngestTracesResponses, InitSessionReplayData, InitSessionReplayErrors, InitSessionReplayResponses, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponses, KillJobData, KillJobErrors, KillJobResponses, KvDelData, KvDelErrors, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponses, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponses, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponses, ListAlertsData, ListAlertsErrors, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsErrors, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenErrors, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesErrors, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponses, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponses, ListDashboardsData, ListDashboardsErrors, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsResponses, ListEventsData, ListEventsResponses, ListEventTypesData, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsErrors, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlErrors, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsErrors, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysErrors, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesErrors, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesErrors, ListMetricNamesResponses, ListModelsData, ListModelsErrors, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansErrors, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysErrors, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponses, ListS3SourcesData, ListS3SourcesErrors, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponses, ListScheduleRunJobsData, ListScheduleRunJobsErrors, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsErrors, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesErrors, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesErrors, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsErrors, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponses, ListUsersData, ListUsersErrors, ListUsersResponses, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponses, LoginData, LoginErrors, LoginResponses, LogoutData, LogoutErrors, LogoutResponses, LookupDnsARecordsData, LookupDnsARecordsErrors, LookupDnsARecordsResponses, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenResponses, MkdirData, MkdirErrors, MkdirResponses, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponses, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponses, ObservabilityFullEventData, ObservabilityFullEventErrors, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsErrors, ObservabilityListEventsResponses, OidcCallbackData, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponses, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponses, PlanRestoreData, PlanRestoreErrors, PlanRestoreResponses, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponses, PreviewAlertData, PreviewAlertErrors, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponses, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponses, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentResponses, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponses, PurgeProjectLogsData, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponses, QueryDataData, QueryDataErrors, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesErrors, QueryGenaiTracesResponses, QueryLogsData, QueryLogsErrors, QueryLogsResponses, QueryMetricsData, QueryMetricsErrors, QueryMetricsResponses, QueryTracesData, QueryTracesErrors, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesErrors, QueryTraceSummariesResponses, ReadFileData, ReadFileErrors, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponses, RecordSpeedMetricsData, RecordSpeedMetricsErrors, RecordSpeedMetricsResponses, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponses, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponses, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponses, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponses, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponses, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponses, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponses, RenameConversationData, RenameConversationErrors, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, ResetPasswordData, ResetPasswordErrors, ResetPasswordResponses, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, RestartContainerData, RestartContainerErrors, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponses, RestoreUserData, RestoreUserErrors, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponses, RetryClusterData, RetryClusterErrors, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponses, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponses, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponses, RootfsGcData, RootfsGcResponses, RootfsReportData, RootfsReportResponses, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponses, RunBackupForSourceData, RunBackupForSourceErrors, RunBackupForSourceResponses, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupErrors, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowErrors, RunScheduleNowResponses, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponses, SearchLogsData, SearchLogsErrors, SearchLogsResponses, SendEmailData, SendEmailErrors, SendEmailResponses, SetDefaultS3SourceData, SetDefaultS3SourceErrors, SetDefaultS3SourceResponses, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponses, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponses, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponses, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponses, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponses, StartAnalysisData, StartAnalysisErrors, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeResponses, StartRestoreData, StartRestoreErrors, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponses, StatPathData, StatPathErrors, StatPathResponses, StopContainerData, StopContainerErrors, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponses, StopServiceData, StopServiceErrors, StopServiceResponses, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponses, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsErrors, TailLogsResponses, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponses, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdErrors, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineErrors, TestProviderKeyInlineResponses, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionErrors, TestS3SourceConnectionResponses, TrackClickData, TrackClickErrors, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentResponses, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanErrors, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponses, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponses, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertErrors, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleErrors, UpdateBackupScheduleResponses, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderResponses, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardErrors, UpdateDashboardResponses, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenResponses, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlErrors, UpdateIpAccessControlResponses, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpResponses, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsResponses, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyErrors, UpdateProviderKeyResponses, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceErrors, UpdateS3SourceResponses, UpdateSelfData, UpdateSelfErrors, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponses, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationErrors, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsErrors, UpdateSpeedMetricsResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderResponses, UpdateWebhookResponses, UpgradePreviewGatewayData, UpgradePreviewGatewayResponses, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponses, UpsertSecretData, UpsertSecretErrors, UpsertSecretResponses, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailResponses, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponses, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponses, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunResponses, WriteFileData, WriteFileErrors, WriteFileResponses, WriteFilesData, WriteFilesErrors, WriteFilesResponses } from './types.gen'; +import type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponses, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainResponses, AddEventsData, AddEventsErrors, AddEventsResponses, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsErrors, AddSessionReplayEventsResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponses, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponses, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeResponses, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponses, AssignRoleData, AssignRoleErrors, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesErrors, AttachScheduleServicesResponses, BlobCopyData, BlobCopyErrors, BlobCopyResponses, BlobDeleteData, BlobDeleteErrors, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponses, BlobDownloadData, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponses, BlobHeadData, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListErrors, BlobListResponses, BlobPutData, BlobPutErrors, BlobPutResponses, BlobStatusData, BlobStatusErrors, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponses, CancelBackupData, CancelBackupErrors, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunErrors, CancelScheduleRunResponses, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceResponses, ChatCompletionsData, ChatCompletionsErrors, ChatCompletionsResponses, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponses, ChunkUploadOptionsData, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsErrors, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartResponses, CliLogoutData, CliLogoutErrors, CliLogoutResponses, CmdData, CmdErrors, CmdKillData, CmdKillErrors, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponses, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponses, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponses, CreateAgentData, CreateAgentErrors, CreateAgentResponses, CreateAlertData, CreateAlertErrors, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleErrors, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponses, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardErrors, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainResponses, CreateDsnData, CreateDsnErrors, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableResponses, CreateFlagData, CreateFlagErrors, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelResponses, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponses, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponses, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponses, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponses, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponses, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentResponses, CreateIpAccessControlData, CreateIpAccessControlErrors, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpResponses, CreateMonitorData, CreateMonitorErrors, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponses, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyErrors, CreateProviderKeyResponses, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteResponses, CreateS3SourceData, CreateS3SourceErrors, CreateS3SourceResponses, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderResponses, CreateUserData, CreateUserErrors, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderResponses, CreateWebhookResponses, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponses, DeleteAlertData, DeleteAlertErrors, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupErrors, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleErrors, DeleteBackupScheduleResponses, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardErrors, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlErrors, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyErrors, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponses, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceErrors, DeleteS3SourceResponses, DeleteScanData, DeleteScanErrors, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponses, DeployFromImageData, DeployFromImageErrors, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticResponses, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceErrors, DetachScheduleServiceResponses, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponses, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponses, DisableMfaData, DisableMfaErrors, DisableMfaResponses, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponses, DomainData, DomainErrors, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponses, EmailStatusData, EmailStatusErrors, EmailStatusResponses, EmbeddingsData, EmbeddingsErrors, EmbeddingsResponses, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponses, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorResponses, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponses, ExecErrors, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportResponses, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponses, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponses, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponses, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponses, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesErrors, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineErrors, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownErrors, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponses, GetAlertData, GetAlertErrors, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponses, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponses, GetBackupData, GetBackupErrors, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailErrors, GetConversationDetailResponses, GetConversationErrors, GetConversationResponses, GetConversationsData, GetConversationsErrors, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponses, GetDashboardData, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponses, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponses, GetDeploymentResponses, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponses, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponses, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceErrors, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponses, GetHealthData, GetHealthErrors, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlErrors, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationErrors, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanErrors, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextErrors, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeErrors, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsErrors, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponses, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsErrors, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingErrors, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponses, GetProjectsData, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysErrors, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthErrors, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponses, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdErrors, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsErrors, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponses, GetQuotaData, GetQuotaErrors, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponses, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponses, GetRestoreCapabilitiesData, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunErrors, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceErrors, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentErrors, GetScanByDeploymentResponses, GetScanData, GetScanErrors, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsErrors, GetSessionReplayEventsResponses, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponses, GetTimeBucketStatsData, GetTimeBucketStatsErrors, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsErrors, GetTodayStatsResponses, GetTraceData, GetTraceErrors, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceErrors, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderErrors, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentErrors, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryErrors, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesErrors, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsErrors, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsErrors, GetVisitorSessionsResponses, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponses, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponses, HasPerformanceMetricsData, HasPerformanceMetricsErrors, HasPerformanceMetricsResponses, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceResponses, IngestLogsByPathData, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesErrors, IngestTracesResponses, InitSessionReplayData, InitSessionReplayErrors, InitSessionReplayResponses, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponses, KillJobData, KillJobErrors, KillJobResponses, KvDelData, KvDelErrors, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponses, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponses, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponses, ListAlertsData, ListAlertsErrors, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsErrors, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenErrors, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesErrors, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponses, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponses, ListDashboardsData, ListDashboardsErrors, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsResponses, ListEventsData, ListEventsResponses, ListEventTypesData, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsErrors, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlErrors, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsErrors, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysErrors, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesErrors, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesErrors, ListMetricNamesResponses, ListModelsData, ListModelsErrors, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansErrors, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysErrors, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponses, ListS3SourcesData, ListS3SourcesErrors, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponses, ListScheduleRunJobsData, ListScheduleRunJobsErrors, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsErrors, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesErrors, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesErrors, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsErrors, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponses, ListUsersData, ListUsersErrors, ListUsersResponses, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponses, LoginData, LoginErrors, LoginResponses, LogoutData, LogoutErrors, LogoutResponses, LookupDnsARecordsData, LookupDnsARecordsErrors, LookupDnsARecordsResponses, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenResponses, MkdirData, MkdirErrors, MkdirResponses, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponses, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponses, ObservabilityFullEventData, ObservabilityFullEventErrors, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsErrors, ObservabilityListEventsResponses, OidcCallbackData, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponses, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponses, PlanRestoreData, PlanRestoreErrors, PlanRestoreResponses, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponses, PreviewAlertData, PreviewAlertErrors, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponses, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponses, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentResponses, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponses, PurgeProjectLogsData, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponses, QueryDataData, QueryDataErrors, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesErrors, QueryGenaiTracesResponses, QueryLogsData, QueryLogsErrors, QueryLogsResponses, QueryMetricsData, QueryMetricsErrors, QueryMetricsResponses, QueryTracesData, QueryTracesErrors, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesErrors, QueryTraceSummariesResponses, ReadFileData, ReadFileErrors, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponses, RecordSpeedMetricsData, RecordSpeedMetricsErrors, RecordSpeedMetricsResponses, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponses, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponses, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponses, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponses, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponses, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponses, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponses, RenameConversationData, RenameConversationErrors, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, ResetPasswordData, ResetPasswordErrors, ResetPasswordResponses, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, RestartContainerData, RestartContainerErrors, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponses, RestoreUserData, RestoreUserErrors, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponses, RetryClusterData, RetryClusterErrors, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponses, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponses, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponses, RootfsGcData, RootfsGcResponses, RootfsReportData, RootfsReportResponses, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponses, RunBackupForSourceData, RunBackupForSourceErrors, RunBackupForSourceResponses, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupErrors, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowErrors, RunScheduleNowResponses, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponses, SearchLogsData, SearchLogsErrors, SearchLogsResponses, SendEmailData, SendEmailErrors, SendEmailResponses, SetDefaultS3SourceData, SetDefaultS3SourceErrors, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentResponses, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponses, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponses, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponses, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponses, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponses, StartAnalysisData, StartAnalysisErrors, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeResponses, StartRestoreData, StartRestoreErrors, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponses, StatPathData, StatPathErrors, StatPathResponses, StopContainerData, StopContainerErrors, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponses, StopServiceData, StopServiceErrors, StopServiceResponses, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponses, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsErrors, TailLogsResponses, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponses, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdErrors, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineErrors, TestProviderKeyInlineResponses, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionErrors, TestS3SourceConnectionResponses, TrackClickData, TrackClickErrors, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentResponses, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanErrors, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponses, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponses, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertErrors, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleErrors, UpdateBackupScheduleResponses, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderResponses, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardErrors, UpdateDashboardResponses, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenResponses, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupResponses, UpdateFlagData, UpdateFlagErrors, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlErrors, UpdateIpAccessControlResponses, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpResponses, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsResponses, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyErrors, UpdateProviderKeyResponses, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceErrors, UpdateS3SourceResponses, UpdateSelfData, UpdateSelfErrors, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponses, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationErrors, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsErrors, UpdateSpeedMetricsResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderResponses, UpdateWebhookResponses, UpgradePreviewGatewayData, UpgradePreviewGatewayResponses, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponses, UpsertSecretData, UpsertSecretErrors, UpsertSecretResponses, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailResponses, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponses, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponses, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunResponses, WriteFileData, WriteFileErrors, WriteFileResponses, WriteFilesData, WriteFilesErrors, WriteFilesResponses } from './types.gen'; export type Options = Options2 & { /** @@ -2688,6 +2688,24 @@ export const getFile = (options: Options(options?: Options): RequestResult => (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/flags/snapshot', + ...options +}); + /** * Get geolocation information for an IP address */ @@ -5611,6 +5629,57 @@ export const getRemoteExternalImage = (opt ...options }); +export const listFlags = (options: Options): RequestResult => (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags', + ...options +}); + +export const createFlag = (options: Options): RequestResult => (options.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + +export const archiveFlag = (options: Options): RequestResult => (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags/{key}', + ...options +}); + +export const getFlag = (options: Options): RequestResult => (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags/{key}', + ...options +}); + +export const updateFlag = (options: Options): RequestResult => (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags/{key}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + +/** + * Set a flag's value in one environment, and/or flip its kill switch. + */ +export const setFlagEnvironment = (options: Options): RequestResult => (options.client ?? client).put({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/flags/{key}/environments/{environment_id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + /** * List all funnels for a project */ diff --git a/web/src/api/client/types.gen.ts b/web/src/api/client/types.gen.ts index d6b7a579c..55bbc3ea8 100644 --- a/web/src/api/client/types.gen.ts +++ b/web/src/api/client/types.gen.ts @@ -1160,6 +1160,11 @@ export type ApplyHostnameModeRequest = { sync_dns?: boolean; }; +export type ArchiveFlagResponse = { + archived_at?: string | null; + key: string; +}; + export type ArchiveMode = 'off' | 'on' | 'always' | 'unknown'; export type AssignRoleRequest = { @@ -3260,6 +3265,33 @@ export type CreateExternalServiceRequest = { version?: string | null; }; +export type CreateFlagRequest = { + /** + * Whether the flag may be exposed on the unauthenticated same-origin + * evaluation endpoint. Defaults to `false`: flags are server-only unless + * explicitly opted in, because targeting rules can encode business logic. + */ + client_visible?: boolean; + /** + * Served whenever evaluation cannot do better. Must match `value_type`. + * + * Left unannotated so utoipa emits a free-form schema: a bool flag's + * default is `false`, not an object, and `value_type = Object` would tell + * every generated client otherwise. + */ + default_value: unknown; + description?: string | null; + /** + * Stable key used in application code. Immutable after create. + */ + key: string; + /** + * Fixed at create: retyping would invalidate every stored value and every + * call site. + */ + value_type: FlagValueType; +}; + export type CreateFunnelRequest = { description?: string | null; name: string; @@ -7006,6 +7038,80 @@ export type FiringSeriesEntry = { series_label: string; }; +export type FlagEnvironmentResponse = { + enabled: boolean; + environment_id: number; + value?: unknown; +}; + +/** + * Note the absence of `salt`: it is never exposed. Publishing the bucketing + * salt would let a client predict, and self-select into, a rollout cohort. + */ +export type FlagListResponse = { + flags: Array; + page: number; + page_size: number; + /** + * Total flags matching the filter, across all pages. + */ + total: number; + total_pages: number; +}; + +export type FlagResponse = { + archived_at?: string | null; + client_visible: boolean; + created_at: string; + default_value: unknown; + description?: string | null; + /** + * Per-environment overrides. Empty means the flag inherits its default + * everywhere. + */ + environments: Array; + id: number; + key: string; + updated_at: string; + value_type: string; +}; + +/** + * A single flag, already resolved down to one environment. This is what the + * evaluator sees and what the SDK caches in memory. + */ +export type FlagSnapshot = { + /** + * Served whenever evaluation cannot do better. Genuinely polymorphic by + * design — the surrounding struct carries the type. + */ + default_value: unknown; + /** + * False means the kill switch is engaged for this environment. + */ + enabled: boolean; + /** + * `None` means "inherit `default_value`". + */ + environment_value?: unknown; + key: string; + value_type: FlagValueType; +}; + +export type FlagSnapshotResponse = { + environment_id: number; + /** + * Flags collapsed to what the evaluator needs, sorted by key so the + * serialized form — and therefore the ETag — is stable. + */ + flags: Array; +}; + +/** + * The declared type of a flag's value. Fixed at create time. + */ +export type FlagValueType = 'bool' | 'string' | 'number' | 'json'; + /** * Forecast model family. */ @@ -14880,6 +14986,19 @@ export type SessionSummary = { started_at: string; }; +export type SetFlagEnvironmentRequest = { + /** + * The kill switch. `false` makes the flag serve its default regardless of + * any override — and, once targeting exists, regardless of any rule. + */ + enabled?: boolean | null; + /** + * Tri-state: absent leaves the override, `null` clears it (inherit the + * flag default), anything else sets it. Must match `value_type`. + */ + value?: unknown; +}; + export type SetPreviewPasswordBody = { /** * Plaintext password to protect the sandbox's preview URLs. Hashed @@ -17037,6 +17156,18 @@ export type UpdateExternalServiceRequest = { }; }; +export type UpdateFlagRequest = { + client_visible?: boolean | null; + /** + * Must match the flag's existing `value_type`. + */ + default_value?: unknown; + /** + * Tri-state: absent leaves it, `null` clears it, a string sets it. + */ + description?: string | null; +}; + export type UpdateGitSettingsRequest = { directory: string; git_provider_connection_id?: number | null; @@ -28572,6 +28703,47 @@ export type GetFileResponses = { export type GetFileResponse = GetFileResponses[keyof GetFileResponses]; +export type GetFlagSnapshotData = { + body?: never; + path?: never; + query?: { + /** + * Required only when the calling token is project-wide rather than scoped + * to a single environment. + */ + environment_id?: number | null; + }; + url: '/flags/snapshot'; +}; + +export type GetFlagSnapshotErrors = { + /** + * Environment could not be determined + */ + 400: unknown; + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type GetFlagSnapshotResponses = { + /** + * Snapshot for the environment + */ + 200: FlagSnapshotResponse; +}; + +export type GetFlagSnapshotResponse = GetFlagSnapshotResponses[keyof GetFlagSnapshotResponses]; + export type GetIpGeolocationData = { body?: never; path: { @@ -40419,6 +40591,287 @@ export type GetRemoteExternalImageResponses = { export type GetRemoteExternalImageResponse = GetRemoteExternalImageResponses[keyof GetRemoteExternalImageResponses]; +export type ListFlagsData = { + body?: never; + path: { + /** + * Project ID + */ + project_id: number; + }; + query?: { + /** + * Include archived flags. Defaults to false. + */ + include_archived?: boolean; + /** + * 1-indexed page number. Defaults to 1. + */ + page?: number | null; + /** + * Items per page. Defaults to 20, capped at 100. + */ + page_size?: number | null; + }; + url: '/projects/{project_id}/flags'; +}; + +export type ListFlagsErrors = { + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type ListFlagsResponses = { + /** + * Flags listed + */ + 200: FlagListResponse; +}; + +export type ListFlagsResponse = ListFlagsResponses[keyof ListFlagsResponses]; + +export type CreateFlagData = { + body: CreateFlagRequest; + path: { + /** + * Project ID + */ + project_id: number; + }; + query?: never; + url: '/projects/{project_id}/flags'; +}; + +export type CreateFlagErrors = { + /** + * Validation error + */ + 400: unknown; + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag key already exists + */ + 409: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type CreateFlagResponses = { + /** + * Flag created + */ + 201: FlagResponse; +}; + +export type CreateFlagResponse = CreateFlagResponses[keyof CreateFlagResponses]; + +export type ArchiveFlagData = { + body?: never; + path: { + /** + * Project ID + */ + project_id: number; + /** + * Flag key + */ + key: string; + }; + query?: never; + url: '/projects/{project_id}/flags/{key}'; +}; + +export type ArchiveFlagErrors = { + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag not found + */ + 404: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type ArchiveFlagResponses = { + /** + * Flag archived + */ + 200: ArchiveFlagResponse; +}; + +export type ArchiveFlagResponse2 = ArchiveFlagResponses[keyof ArchiveFlagResponses]; + +export type GetFlagData = { + body?: never; + path: { + /** + * Project ID + */ + project_id: number; + /** + * Flag key + */ + key: string; + }; + query?: never; + url: '/projects/{project_id}/flags/{key}'; +}; + +export type GetFlagErrors = { + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag not found + */ + 404: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type GetFlagResponses = { + /** + * Flag retrieved + */ + 200: FlagResponse; +}; + +export type GetFlagResponse = GetFlagResponses[keyof GetFlagResponses]; + +export type UpdateFlagData = { + body: UpdateFlagRequest; + path: { + /** + * Project ID + */ + project_id: number; + /** + * Flag key + */ + key: string; + }; + query?: never; + url: '/projects/{project_id}/flags/{key}'; +}; + +export type UpdateFlagErrors = { + /** + * Validation error + */ + 400: unknown; + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag not found + */ + 404: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type UpdateFlagResponses = { + /** + * Flag updated + */ + 200: FlagResponse; +}; + +export type UpdateFlagResponse = UpdateFlagResponses[keyof UpdateFlagResponses]; + +export type SetFlagEnvironmentData = { + body: SetFlagEnvironmentRequest; + path: { + /** + * Project ID + */ + project_id: number; + /** + * Flag key + */ + key: string; + /** + * Environment ID + */ + environment_id: number; + }; + query?: never; + url: '/projects/{project_id}/flags/{key}/environments/{environment_id}'; +}; + +export type SetFlagEnvironmentErrors = { + /** + * Validation error + */ + 400: unknown; + /** + * Unauthorized + */ + 401: unknown; + /** + * Insufficient permissions + */ + 403: unknown; + /** + * Flag or environment not found + */ + 404: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type SetFlagEnvironmentResponses = { + /** + * Environment value set + */ + 200: FlagEnvironmentResponse; +}; + +export type SetFlagEnvironmentResponse = SetFlagEnvironmentResponses[keyof SetFlagEnvironmentResponses]; + export type ListFunnelsData = { body?: never; path: { diff --git a/web/src/components/dashboard/Sidebar.tsx b/web/src/components/dashboard/Sidebar.tsx index 55b066bd1..af5411019 100644 --- a/web/src/components/dashboard/Sidebar.tsx +++ b/web/src/components/dashboard/Sidebar.tsx @@ -34,6 +34,7 @@ import { FileText, FileLock2, Filter, + Flag, Folder, Gauge, GitBranch, @@ -931,6 +932,7 @@ const projectBaseNav: ProjectNavItem[] = [ url: 'environment-variables', icon: KeyRound, }, + { title: 'Feature Flags', url: 'flags', icon: Flag }, { title: 'Domains', url: 'domains', icon: Globe }, { title: 'Git', url: 'git', icon: GitFork }, { title: 'Logs', url: 'runtime', icon: ScrollText }, diff --git a/web/src/components/project/flags/CreateFlagDialog.tsx b/web/src/components/project/flags/CreateFlagDialog.tsx new file mode 100644 index 000000000..3f97dfa10 --- /dev/null +++ b/web/src/components/project/flags/CreateFlagDialog.tsx @@ -0,0 +1,253 @@ +import { createFlagMutation } from '@/api/client/@tanstack/react-query.gen' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group' +import { Switch } from '@/components/ui/switch' +import { Textarea } from '@/components/ui/textarea' +import { cn } from '@/lib/utils' +import { useMutation } from '@tanstack/react-query' +import { Loader2 } from 'lucide-react' +import { useState } from 'react' +import { toast } from 'sonner' +import { FlagValueField } from './FlagValueField' +import { + FLAG_VALUE_TYPES, + flagErrorMessage, + parseFlagValue, + validateFlagKey, + type FlagValueType, +} from './flag-value' + +interface CreateFlagDialogProps { + projectId: number + open: boolean + onOpenChange: (open: boolean) => void + onCreated: () => void +} + +const DEFAULT_FOR_TYPE: Record = { + bool: 'false', + string: '', + number: '0', + json: '{}', +} + +export function CreateFlagDialog({ + projectId, + open, + onOpenChange, + onCreated, +}: CreateFlagDialogProps) { + const [key, setKey] = useState('') + const [valueType, setValueType] = useState('bool') + const [defaultValue, setDefaultValue] = useState(DEFAULT_FOR_TYPE.bool) + const [description, setDescription] = useState('') + const [clientVisible, setClientVisible] = useState(false) + const [keyError, setKeyError] = useState(null) + const [valueError, setValueError] = useState(null) + + const reset = () => { + setKey('') + setValueType('bool') + setDefaultValue(DEFAULT_FOR_TYPE.bool) + setDescription('') + setClientVisible(false) + setKeyError(null) + setValueError(null) + } + + const create = useMutation({ + ...createFlagMutation(), + onSuccess: () => { + toast.success(`Flag ${key} created`) + reset() + onOpenChange(false) + onCreated() + }, + onError: (error) => { + toast.error(flagErrorMessage(error, 'Could not create the flag')) + }, + }) + + const handleTypeChange = (next: string) => { + const type = next as FlagValueType + setValueType(type) + // Reset the default to something valid for the new type rather than + // leaving "abc" sitting in a number field. + setDefaultValue(DEFAULT_FOR_TYPE[type]) + setValueError(null) + } + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault() + + const trimmedKey = key.trim() + const keyProblem = validateFlagKey(trimmedKey) + const parsed = parseFlagValue(defaultValue, valueType) + + setKeyError(keyProblem) + setValueError(parsed.ok ? null : parsed.error) + if (keyProblem || !parsed.ok) return + + create.mutate({ + path: { project_id: projectId }, + body: { + key: trimmedKey, + value_type: valueType, + default_value: parsed.value, + description: description.trim() || null, + client_visible: clientVisible, + }, + }) + } + + return ( + { + if (!next) reset() + onOpenChange(next) + }} + > + +
+ + New feature flag + + The key and type are permanent. Everything else can change later. + + + +
+
+ + { + setKey(e.target.value) + if (keyError) setKeyError(null) + }} + placeholder="checkout.v2" + spellCheck={false} + autoComplete="off" + className={cn( + 'font-mono text-sm', + keyError && + 'border-destructive focus-visible:ring-destructive' + )} + /> + {keyError ? ( +

{keyError}

+ ) : ( +

+ Lowercase letters, digits, dot, underscore and hyphen. Used + verbatim in your code. +

+ )} +
+ +
+ + + {FLAG_VALUE_TYPES.map((option) => ( + + ))} + +
+ + { + setDefaultValue(next) + if (valueError) setValueError(null) + }} + error={valueError} + description="Served whenever nothing more specific applies, and whenever the flag is disabled." + /> + +
+ +