{
  "openapi": "3.1.0",
  "info": {
    "title": "Rustrak",
    "description": "Ultra-lightweight error tracking server compatible with Sentry SDKs",
    "contact": {
      "name": "Rustrak Team"
    },
    "license": {
      "name": "AGPL-3.0-only",
      "identifier": "AGPL-3.0-only"
    },
    "version": "0.25.0"
  },
  "paths": {
    "/api/0/issues/{issue_id}/": {
      "get": {
        "tags": [
          "Sentry API"
        ],
        "summary": "GET /api/0/issues/{issue_id}/",
        "description": "One issue with its releases and its 24h and 30d series (Sentry's\n`GroupDetailsEndpoint`). Also served under `/groups/` and the\norganization-scoped paths, as Sentry does.",
        "operationId": "sentry.getIssue",
        "parameters": [
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue id (`numeric_id`)",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Issue details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentryIssueDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Sentry API"
        ],
        "summary": "PUT /api/0/issues/{issue_id}/",
        "description": "Sets an issue's status and returns the issue (Sentry's\n`GroupDetailsEndpoint.put`). The change goes through Rustrak's own\nissue update, so it is recorded and mirrored like any other.",
        "operationId": "sentry.updateIssue",
        "parameters": [
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue id (`numeric_id`)",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IssueUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Issue updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentryIssue"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/issues/{issue_id}/events/latest/": {
      "get": {
        "tags": [
          "Sentry API"
        ],
        "summary": "GET /api/0/issues/{issue_id}/events/latest/",
        "description": "The issue's most recent event (Sentry's `GroupEventDetailsEndpoint`,\n`issues/endpoints/group_event_details.py`).",
        "operationId": "sentry.getLatestEvent",
        "parameters": [
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue id (`numeric_id`)",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The issue's latest event",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentryEvent"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/organizations/": {
      "get": {
        "tags": [
          "Sentry API"
        ],
        "summary": "GET /api/0/organizations/",
        "description": "The organizations the token belongs to (Sentry's\n`OrganizationIndexEndpoint`): always the one synthetic org.",
        "operationId": "sentry.listOrganizations",
        "responses": {
          "200": {
            "description": "The synthetic organization",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SentryOrganization"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/organizations/{org_slug}/": {
      "get": {
        "tags": [
          "Source Maps"
        ],
        "summary": "GET /api/0/organizations/{org_slug}/\nAlways returns 200 with synthetic org data — sentry-cli validates this before uploading.",
        "operationId": "sourceMaps.orgDetails",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Synthetic org metadata accepted by sentry-cli",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/0/organizations/{org_slug}/artifactbundle/assemble/": {
      "post": {
        "tags": [
          "Source Maps"
        ],
        "summary": "POST /api/0/organizations/{org_slug}/artifactbundle/assemble/",
        "operationId": "sourceMaps.artifactBundleAssemble",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssembleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Assembly job state (not_found / created / assembling / ok / error). Missing chunks are listed in missingChunks.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssembleResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request or checksum mismatch",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/organizations/{org_slug}/chunk-upload/": {
      "get": {
        "tags": [
          "Source Maps"
        ],
        "summary": "GET /api/0/organizations/{org_slug}/chunk-upload/",
        "operationId": "sourceMaps.chunkUploadCapability",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Chunk upload capabilities and URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChunkUploadOptions"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Source Maps"
        ],
        "summary": "POST /api/0/organizations/{org_slug}/chunk-upload/",
        "operationId": "sourceMaps.chunkUpload",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "One or more binary chunk files. Field names may be SHA-1 hashes (v2 protocol) or arbitrary names like 'file' (v3.x protocol).",
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ChunkUploadBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Chunks stored successfully"
          },
          "400": {
            "description": "Invalid multipart or chunk too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing source-maps:create on every project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/organizations/{org_slug}/repos/": {
      "get": {
        "tags": [
          "Sentry API"
        ],
        "summary": "GET /api/0/organizations/{org_slug}/repos/",
        "description": "The code repositories connected to the organization (Sentry's\n`OrganizationRepositoriesEndpoint`). Rustrak connects none through\nSentry's integrations, so the list is always empty.",
        "operationId": "sentry.listRepos",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug (synthetic — accepted and ignored)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Connected repositories: always none",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/projects/": {
      "get": {
        "tags": [
          "Sentry API"
        ],
        "summary": "GET /api/0/projects/",
        "description": "The projects the token can see, newest first (Sentry's\n`ProjectIndexEndpoint`, `core/endpoints/project_index.py`).",
        "operationId": "sentry.listProjects",
        "parameters": [
          {
            "name": "per_page",
            "in": "query",
            "description": "Page size, at most 100 (default: 100).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "A cursor from the `Link` header.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Projects, newest first; paginated by the `Link` header",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SentryProject"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/projects/{org_slug}/{project_slug}/files/difs/assemble/": {
      "post": {
        "tags": [
          "Source Maps"
        ],
        "summary": "Assemble uploaded chunks into debug information files (ProGuard mappings, JVM source bundles).",
        "description": "Sentry's `DifAssembleEndpoint`: the body maps each file's SHA-1 to its\nname, chunks and optional debug ID, and the answer maps it to its state.",
        "operationId": "debugFiles.assemble",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_slug",
            "in": "path",
            "description": "Project slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/DifAssembleFile"
                },
                "propertyNames": {
                  "type": "string"
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Assembly state per file checksum (not_found / created / assembling / ok / error)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "$ref": "#/components/schemas/AssembleResponse"
                  },
                  "propertyNames": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/projects/{org_slug}/{project_slug}/files/dsyms/": {
      "post": {
        "tags": [
          "Source Maps"
        ],
        "summary": "Upload a zip of debug information files (the path `sentry-cli upload-proguard` takes).",
        "description": "Sentry's `DebugFilesEndpoint.post` processes the zip in the request.\nHere each file goes through the assembly worker instead, the same as a\nchunked upload, because building a ProGuard cache can take gigabytes.\nOnly ProGuard mappings are recognised; other entries are skipped.",
        "operationId": "debugFiles.upload",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_slug",
            "in": "path",
            "description": "Project slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "A `file` part: a zip of debug files, such as `proguard/<uuid>.txt`",
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DifUploadBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "The debug files queued for processing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DebugFileResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid upload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/projects/{org_slug}/{project_slug}/files/source-maps/": {
      "get": {
        "tags": [
          "Source Maps"
        ],
        "summary": "GET /api/0/projects/{org_slug}/{project_slug}/files/source-maps/",
        "operationId": "sourceMaps.list",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_slug",
            "in": "path",
            "description": "Project slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of uploaded source map files",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SourceMapList"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/projects/{org_slug}/{project_slug}/issues/": {
      "get": {
        "tags": [
          "Sentry API"
        ],
        "summary": "GET /api/0/projects/{org_slug}/{project_slug}/issues/",
        "description": "A project's issues, filtered by `query`, sorted by `sort` and paginated\nby `cursor` (Sentry's `ProjectGroupIndexEndpoint`,\n`issues/endpoints/project_group_index.py`).",
        "operationId": "sentry.listIssues",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug (synthetic — accepted and ignored)",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_slug",
            "in": "path",
            "description": "Project slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "query",
            "in": "query",
            "description": "Search: `is:unresolved|resolved|ignored` and free text (default: `is:unresolved`).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "`date` (default), `new` or `freq`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size, at most 100 (default: 100).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "A cursor from the `Link` header.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "statsPeriod",
            "in": "query",
            "description": "`24h` (default), `14d`, or empty for no stats.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only issues seen in this environment, counted there.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Issues; paginated by the `Link` header",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SentryIssue"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/projects/{org_slug}/{project_slug}/releases/": {
      "post": {
        "tags": [
          "Releases"
        ],
        "summary": "POST /api/0/projects/{org_slug}/{project_slug}/releases/",
        "description": "Sentry-compatible release creation. Idempotent: repeating the same\n`(project, version)` returns 208 rather than erroring — sentry-cli and JS\nbundler plugins call this on every build. Triggers date-based regression\nclearing (see [`crate::services::issue::IssueService::finalize_release`])\non every call, not just the new-row branch: `finalize_release`'s own\n`UPDATE ... WHERE` is idempotent (a repeat run affects 0 rows once nothing\nis left to clear), so this also self-heals a prior call that created the\nrow but failed before clearing ran — a plain `if created` gate would\notherwise skip clearing forever once a retry lands on the 208 branch.",
        "operationId": "releases.create",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug (synthetic — accepted and ignored)",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_slug",
            "in": "path",
            "description": "Project slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRelease"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Release created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseResponse"
                }
              }
            }
          },
          "208": {
            "description": "Release already exists — no duplicate created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid version",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/projects/{org_slug}/{project_slug}/releases/{version}/": {
      "put": {
        "tags": [
          "Releases"
        ],
        "summary": "PUT /api/0/projects/{org_slug}/{project_slug}/releases/{version}/",
        "description": "Generic partial update (`ref`, `url`, `dateReleased`). Setting\n`dateReleased` IS \"finalize\" — there is no separate status flag.",
        "operationId": "releases.finalize",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug (synthetic — accepted and ignored)",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_slug",
            "in": "path",
            "description": "Project slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version",
            "in": "path",
            "description": "Release version",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRelease"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Release updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project or release not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/0/projects/{org_slug}/{project_slug}/user-feedback/": {
      "post": {
        "tags": [
          "Sentry API"
        ],
        "summary": "POST /api/0/projects/{org_slug}/{project_slug}/user-feedback/",
        "description": "Submit a user report about an error event (Sentry's\n`ProjectUserReportsEndpoint`, `feedback/endpoints/project_user_reports.py`).\nAccepts `Authorization: DSN <dsn>` as well as a token; the report becomes a\nfeedback, as the `user_report` envelope item does.",
        "operationId": "sentry.submitUserFeedback",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug (ignored)",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_slug",
            "in": "path",
            "description": "Project slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SentryUserReportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The report, or an empty body under DSN auth",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentryUserReport"
                }
              }
            }
          },
          "400": {
            "description": "Invalid report",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/access/catalog": {
      "get": {
        "tags": [
          "Access"
        ],
        "summary": "Lists every resource a permission can name, with its module, scope and actions.",
        "operationId": "access.catalog",
        "responses": {
          "200": {
            "description": "Every resource a permission can name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalog"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/access/me": {
      "get": {
        "tags": [
          "Access"
        ],
        "summary": "Returns what the caller may do, on the instance and on each project.",
        "operationId": "access.me",
        "responses": {
          "200": {
            "description": "What the caller may do",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MyAccess"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/github": {
      "get": {
        "tags": [
          "GitHub"
        ],
        "summary": "GET /api/github",
        "operationId": "github.status",
        "responses": {
          "200": {
            "description": "GitHub App and installations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitHubStatus"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "GitHub"
        ],
        "summary": "DELETE /api/github",
        "operationId": "github.disconnect",
        "responses": {
          "204": {
            "description": "GitHub App removed"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/github/callback": {
      "get": {
        "tags": [
          "GitHub"
        ],
        "summary": "GET /api/github/callback: GitHub sends the browser here after creating the\napp; the code trades for its credentials.",
        "operationId": "github.callback",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "description": "Manifest code from GitHub",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "description": "State issued by the manifest step",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Browser redirect to the integrations page"
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/github/installed": {
      "get": {
        "tags": [
          "GitHub"
        ],
        "summary": "GET /api/github/installed: GitHub sends the browser here after the app is\ninstalled on an account.",
        "operationId": "github.installed",
        "parameters": [
          {
            "name": "installation_id",
            "in": "query",
            "description": "GitHub installation ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Browser redirect to the integrations page"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/github/issue-template": {
      "put": {
        "tags": [
          "GitHub"
        ],
        "summary": "PUT /api/github/issue-template: the labels, title prefix and body footer\nevery GitHub issue starts with, before a project's own.",
        "operationId": "github.putIssueTemplate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IssueTemplate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Template saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueTemplate"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/github/manifest": {
      "post": {
        "tags": [
          "GitHub"
        ],
        "summary": "POST /api/github/manifest: what the dashboard posts to GitHub so GitHub\ncreates an app already configured for this server.",
        "operationId": "github.manifest",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManifestRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Form to post to GitHub",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManifestResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/github/me": {
      "get": {
        "tags": [
          "GitHub"
        ],
        "summary": "GET /api/github/me: the GitHub username assignees sync through.",
        "operationId": "github.getMyLogin",
        "responses": {
          "200": {
            "description": "Your GitHub username",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitHubLogin"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "GitHub"
        ],
        "summary": "PUT /api/github/me",
        "operationId": "github.putMyLogin",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GitHubLogin"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "GitHub username saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitHubLogin"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/github/repositories": {
      "get": {
        "tags": [
          "GitHub"
        ],
        "summary": "GET /api/github/repositories?project_id=: the repositories a project can\npoint at, for whoever may change that project's settings.",
        "operationId": "github.repositories",
        "parameters": [
          {
            "name": "project_id",
            "in": "query",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Repositories the installations reach",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GitHubRepository"
                  }
                }
              }
            }
          },
          "400": {
            "description": "GitHub is not connected",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/github/webhook": {
      "post": {
        "tags": [
          "GitHub"
        ],
        "summary": "POST /api/github/webhook: public, and trusted only through the signature\nGitHub computes with the app's webhook secret.",
        "operationId": "github.webhook",
        "requestBody": {
          "description": "GitHub event payload, signed in X-Hub-Signature-256",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Event processed"
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid signature",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No GitHub App connected",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/integrations": {
      "get": {
        "tags": [
          "Alert Channels"
        ],
        "summary": "Lists the channels alerts can go through.",
        "description": "`integrations:read` sees their credentials masked, `integrations:update` in\nfull. Holding an alert-rules permission on any project is enough for the\nrest, without them: choosing where a rule notifies takes a channel's name,\nnot its secrets.",
        "operationId": "alertChannels.list",
        "responses": {
          "200": {
            "description": "List of notification channels",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertIntegration"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing integrations:read and every alert-rules permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Alert Channels"
        ],
        "summary": "POST /api/alert-channels",
        "operationId": "alertChannels.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAlertIntegration"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Channel created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertIntegration"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/integrations/preview-template": {
      "post": {
        "tags": [
          "Alert Channels"
        ],
        "summary": "POST /api/integrations/preview-template",
        "description": "Renders a Custom Webhook template against a sample payload and hands back\nthe body that would be sent. The dashboard cannot run the template engine,\nso it asks while the reader types; going through the dispatcher's own\nrenderer is what keeps the preview from disagreeing with a delivery.",
        "operationId": "alertChannels.previewTemplate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewTemplateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Rendered body, or why it would not render",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreviewTemplateResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/integrations/{id}": {
      "get": {
        "tags": [
          "Alert Channels"
        ],
        "summary": "GET /api/alert-channels/{id}",
        "operationId": "alertChannels.get",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Channel details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertIntegration"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Alert Channels"
        ],
        "summary": "DELETE /api/alert-channels/{id}",
        "operationId": "alertChannels.delete",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Channel deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Alert Channels"
        ],
        "summary": "PATCH /api/alert-channels/{id}",
        "operationId": "alertChannels.update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAlertIntegration"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Channel updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertIntegration"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/integrations/{id}/test": {
      "post": {
        "tags": [
          "Alert Channels"
        ],
        "summary": "POST /api/integrations/{id}/test",
        "operationId": "alertChannels.test",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestIntegrationBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Test notification sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestChannelResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/invitations": {
      "get": {
        "tags": [
          "Invitations"
        ],
        "summary": "GET /api/invitations — list invitations (needs `invitations:read`)",
        "operationId": "invitations.list",
        "responses": {
          "200": {
            "description": "List of invitations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InvitationResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Invitations"
        ],
        "summary": "POST /api/invitations — create an invitation (needs `invitations:create`)",
        "description": "With `send_email: true` the invite link is also emailed. A failed send\nstill creates the invitation, with `email_sent_at: null`, so its link can\nbe shared by hand or the email resent.",
        "operationId": "invitations.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInvitation"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Invitation created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid role, or send_email while invitation emails are not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Email already a user or pending invite",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/invitations/email-status": {
      "get": {
        "tags": [
          "Invitations"
        ],
        "summary": "GET /api/invitations/email-status — whether invitation emails can be sent (needs `invitations:read`)",
        "operationId": "invitations.emailStatus",
        "responses": {
          "200": {
            "description": "Whether invitation emails can be sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Reading the email integrations failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/invitations/{id}": {
      "delete": {
        "tags": [
          "Invitations"
        ],
        "summary": "DELETE /api/invitations/{id} — revoke a pending invitation (needs `invitations:delete`)",
        "operationId": "invitations.revoke",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Invitation id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Invitation revoked"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Pending invitation not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/invitations/{id}/resend": {
      "post": {
        "tags": [
          "Invitations"
        ],
        "summary": "POST /api/invitations/{id}/resend — email the invite link again (needs `invitations:create`)",
        "operationId": "invitations.resend",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Invitation id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation email sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invitation expired or already used, or invitation emails are not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Invitation not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "The email could not be sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/oauth/authorize": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "Verifies an authorization request and says who is asking.",
        "operationId": "oauth.getAuthorization",
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "resource",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The verified client asking for access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorizationInfo"
                }
              }
            }
          },
          "400": {
            "description": "The request cannot be trusted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Approves or denies an authorization request as the signed-in user.",
        "operationId": "oauth.decideAuthorization",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthorizationDecision"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Where to send the browser",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorizationRedirect"
                }
              }
            }
          },
          "400": {
            "description": "The request cannot be trusted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/grants": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "Lists the assistants connected to the signed-in user's account.",
        "operationId": "oauth.listGrants",
        "responses": {
          "200": {
            "description": "Assistants connected to your account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/OAuthGrant"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/grants/{id}": {
      "delete": {
        "tags": [
          "OAuth"
        ],
        "summary": "Disconnects an assistant: its tokens stop working at once.",
        "operationId": "oauth.revokeGrant",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Connection ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Disconnected"
          },
          "401": {
            "description": "Not signed in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not one of your connections",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "GET /api/projects - List projects with pagination",
        "description": "Only the projects the caller holds a permission on.",
        "operationId": "projects.list",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort order direction (default: desc = newest first)",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/SortOrder"
            }
          },
          {
            "name": "stats_period",
            "in": "query",
            "description": "Window for the per-project stats on each row (e.g. `24h`, `7d`).\n\nOmitted means the caller does not want stats at all, and the extra\naggregate queries are skipped entirely — this is what keeps the plain\n`GET /api/projects` that SDK tooling and the project picker use as\ncheap as it was before the list table grew a sparkline. Sentry's own\nprojects endpoint gates its `stats` field on `?statsPeriod=` the same\nway.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of projects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Response with DSN included",
                        "required": [
                          "id",
                          "name",
                          "slug",
                          "sentry_key",
                          "dsn",
                          "stored_event_count",
                          "digested_event_count",
                          "rate_limited_event_count",
                          "rate_limit_per_minute",
                          "rate_limit_per_hour",
                          "created_at",
                          "updated_at",
                          "platform",
                          "disabled_products",
                          "product_order"
                        ],
                        "properties": {
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "digested_event_count": {
                            "type": "integer",
                            "format": "int32"
                          },
                          "disabled_products": {
                            "type": "array",
                            "items": {
                              "$ref": "#/components/schemas/Product"
                            },
                            "description": "Products whose data this project drops at ingest."
                          },
                          "dsn": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "id": {
                            "type": "integer",
                            "format": "int32"
                          },
                          "name": {
                            "type": "string"
                          },
                          "platform": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "product_order": {
                            "type": "array",
                            "items": {
                              "$ref": "#/components/schemas/Product"
                            },
                            "description": "The order its sidebar lists the products in; the ones missing follow\nin their default order."
                          },
                          "rate_limit_per_hour": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int64"
                          },
                          "rate_limit_per_minute": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int64",
                            "description": "The project's own limits, or `null` when it follows the operator's."
                          },
                          "rate_limited_event_count": {
                            "type": "integer",
                            "format": "int64",
                            "description": "Events the quota dropped after ingest had accepted them."
                          },
                          "sentry_key": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "The DSN's public key: its 32 hex digits in hyphenated UUID form\n(8-4-4-4-12), not necessarily an RFC 4122 UUID. The DSN carries the\nsame key without hyphens.\n\n`null` without `client-keys:read` on the project, as is `dsn`."
                          },
                          "slug": {
                            "type": "string"
                          },
                          "stats": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/ProjectListStats",
                                "description": "Present only when the request asked for `?stats_period=`.\n\nAbsent rather than zeroed when unrequested: a caller that did not ask\nmust be able to tell \"no stats were computed\" from \"this project is\nquiet\", and only one of those should render an empty sparkline."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "stored_event_count": {
                            "type": "integer",
                            "format": "int32"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "POST /api/projects - Create a new project",
        "description": "Needs `projects:create` and a permission on at least one project, because\nthe creator's own roles extend to the new one. A token limited to chosen\nprojects can create one, but its list does not grow to reach it.",
        "operationId": "projects.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProject"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Project created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing projects:create, or no permission on projects",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{id}": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "GET /api/projects/{id} - Get a project by ID",
        "operationId": "projects.get",
        "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"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Projects"
        ],
        "summary": "DELETE /api/projects/{id} - Delete a project",
        "operationId": "projects.delete",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Project deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Projects"
        ],
        "summary": "PATCH /api/projects/{id} - Update a project",
        "operationId": "projects.update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProject"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Project updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/conversations": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/conversations\nLists conversations -- traces sharing a `gen_ai.conversation.id` -- the most recently active first.",
        "operationId": "agents.conversations",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated agent conversations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "One conversation: every trace sharing a `gen_ai.conversation.id`, each a\nturn, with the totals of all of them -- a row of Sentry's conversations.",
                        "required": [
                          "conversation_id",
                          "turn_count",
                          "agent_names",
                          "llm_call_count",
                          "tool_call_count",
                          "total_tokens",
                          "error_count",
                          "first_seen",
                          "last_seen"
                        ],
                        "properties": {
                          "agent_names": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Every agent that ran in it, earliest first."
                          },
                          "conversation_id": {
                            "type": "string"
                          },
                          "error_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "first_seen": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "description": "From the spans' start times, else their end times; `null` when no span\nof the conversation carries either, as a transaction's child can."
                          },
                          "last_seen": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "llm_call_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "tool_call_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "total_tokens": {
                            "type": "number",
                            "format": "double",
                            "description": "`agent` spans excluded, as everywhere: their usage rolls up their children."
                          },
                          "turn_count": {
                            "type": "integer",
                            "format": "int64",
                            "description": "Traces in the conversation."
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/conversations/{conversation_id}": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/conversations/{conversation_id}\nReturns every AI span of a conversation's turns, oldest first, with its input and output.",
        "operationId": "agents.conversation",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "conversation_id",
            "in": "path",
            "description": "The gen_ai.conversation.id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The conversation's AI spans across its turns",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentConversation"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/duration": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/duration\nTime-bucketed avg/p95 duration for `agent`/`ai_client` spans.",
        "operationId": "agents.duration",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "interval_hours",
            "in": "query",
            "description": "Bucket width in hours (default: 1).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Avg/p95 duration over time for agent runs and LLM calls",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentDurationPoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/environments": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/environments\nThe options the environment filter offers, read from the data rather than\nhardcoded — an installation may name its environments anything.",
        "operationId": "agents.environments",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Environments present in this project's AI spans",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/models": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/models",
        "operationId": "agents.modelsTable",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Per-model volume, failures, latency and token split",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentModelRow"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/models/calls": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/models/calls\nTop models by LLM call count (`gen_ai.operation.type:ai_client`).",
        "operationId": "agents.modelsCalls",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max rows returned (default: 3, matching Sentry's own widget cap).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Top LLM call counts by response model",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenAiBreakdownRow"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/models/tokens": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/models/tokens\nTop models by total tokens used (`gen_ai.operation.type:ai_client`).",
        "operationId": "agents.modelsTokens",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max rows returned (default: 3, matching Sentry's own widget cap).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Top total tokens used by response model",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenAiBreakdownRow"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/runs": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/runs\nTime-bucketed count of agent-run spans (`gen_ai.operation.type:agent`).",
        "operationId": "agents.runs",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "interval_hours",
            "in": "query",
            "description": "Bucket width in hours (default: 1).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Agent runs over time",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentTimeseriesPoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/summary": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/summary\nAgent runs, LLM calls, tool calls, errors, tokens and latency over the\nselected window — the numbers the six charts cannot state outright.",
        "operationId": "agents.summary",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Headline totals for the selected window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/tools": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/tools\nTop tools by call count (`gen_ai.operation.type:tool`).",
        "operationId": "agents.tools",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max rows returned (default: 3, matching Sentry's own widget cap).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Top tool call counts by tool name",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenAiBreakdownRow"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/tools/stats": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/tools/stats",
        "operationId": "agents.toolsTable",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Per-tool call volume, failures and latency",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentToolRow"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/agents/traces": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "GET /api/projects/{project_id}/agents/traces\nPaginated per-trace_id aggregate (duration, tokens, tool usage) across\nall AI spans sharing that trace, regardless of origin.",
        "operationId": "agents.traces",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period_hours",
            "in": "query",
            "description": "Lookback window in hours (default: all time, no filter). The dashboard\napplies one window to every widget, and this table is one of them.",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Restrict to spans reporting this environment (default: all).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          },
          {
            "name": "agent",
            "in": "query",
            "description": "Only the traces where this agent ran.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "model",
            "in": "query",
            "description": "Only the traces that called this model (response model, else request).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "tool",
            "in": "query",
            "description": "Only the traces that used this tool.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "errors",
            "in": "query",
            "description": "Only the traces with a failing AI span.",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "How to rank them; newest first by default.",
            "required": false,
            "schema": {
              "type": "string",
              "description": "How the agent traces are ranked; every ranking but newest is largest first.",
              "enum": [
                "newest",
                "duration",
                "tokens",
                "llm_calls",
                "tool_calls",
                "errors"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated agent traces",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "One row of the Traces table — per-`trace_id` aggregate across all AI\nspans (standalone and transaction-embedded) sharing that trace.",
                        "required": [
                          "trace_id",
                          "agent_names",
                          "duration_ms",
                          "total_tokens",
                          "tool_call_count",
                          "llm_call_count",
                          "error_count",
                          "started_at"
                        ],
                        "properties": {
                          "agent_names": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Every distinct agent that ran in this trace, earliest first. A trace\nwith handoffs involves more than one, so this is a list rather than a\nsingle root name — Sentry's own Traces table shows them all."
                          },
                          "duration_ms": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double",
                            "description": "Duration of the root/longest AI span in this trace, in milliseconds."
                          },
                          "error_count": {
                            "type": "integer",
                            "format": "int64",
                            "description": "AI spans in this trace whose status is set and not `ok`."
                          },
                          "llm_call_count": {
                            "type": "integer",
                            "format": "int64",
                            "description": "`ai_client` spans in this trace — how many times a model was actually\ncalled, which is what separates a one-shot answer from an agent loop."
                          },
                          "started_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "tool_call_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "total_tokens": {
                            "type": "number",
                            "format": "double"
                          },
                          "trace_id": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/alert-history": {
      "get": {
        "tags": [
          "Alert Rules"
        ],
        "summary": "GET /api/projects/{project_id}/alert-history",
        "operationId": "alertRules.listHistory",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max records to return (default 50, max 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "rule_id",
            "in": "query",
            "description": "Only this alert rule's deliveries",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertHistory"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameter",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/alert-history/daily": {
      "get": {
        "tags": [
          "Alert Rules"
        ],
        "summary": "Count a project's alert deliveries per day, by outcome.",
        "operationId": "alertRules.historyByDay",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "days",
            "in": "query",
            "description": "Days back, today included (default 14, max 90)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "rule_id",
            "in": "query",
            "description": "Only this alert rule's deliveries",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deliveries per UTC day, oldest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertHistoryDay"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameter",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/alert-rules": {
      "get": {
        "tags": [
          "Alert Rules"
        ],
        "summary": "GET /api/projects/{project_id}/alert-rules",
        "operationId": "alertRules.list",
        "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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Alert Rules"
        ],
        "summary": "POST /api/projects/{project_id}/alert-rules",
        "operationId": "alertRules.create",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAlertRule"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Alert rule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/alert-rules/{rule_id}": {
      "get": {
        "tags": [
          "Alert Rules"
        ],
        "summary": "GET /api/projects/{project_id}/alert-rules/{rule_id}",
        "operationId": "alertRules.get",
        "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"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Alert Rules"
        ],
        "summary": "DELETE /api/projects/{project_id}/alert-rules/{rule_id}",
        "operationId": "alertRules.delete",
        "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"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Alert Rules"
        ],
        "summary": "PATCH /api/projects/{project_id}/alert-rules/{rule_id}",
        "operationId": "alertRules.update",
        "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/UpdateAlertRule"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Alert rule updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/attachments/{attachment_id}": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "GET /api/projects/{project_id}/attachments/{attachment_id}\nDownloads an attachment. Only a real image is served inline; anything\nelse, whatever type it claims, is a download that never runs.",
        "operationId": "events.downloadAttachment",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "attachment_id",
            "in": "path",
            "description": "Attachment ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file: inline when its bytes are a PNG, JPEG, GIF or WebP image, a download otherwise",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "$ref": "#/components/schemas/AttachmentBytes"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/environments": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /api/projects/{project_id}/environments\nLists the environments a project's issues have been seen in, by name.",
        "operationId": "environments.list",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Environments the project's issues have been seen in",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/events/sentry/{event_id}": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "Resolve the ID returned by a Sentry SDK without already knowing the issue.",
        "operationId": "events.getBySentryId",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "description": "Client-supplied Sentry event ID: 32 hex digits, compact or hyphenated",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Full event detail, including its issue ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Event or accessible project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/events/stats": {
      "get": {
        "tags": [
          "Stats"
        ],
        "summary": "GET /api/projects/{project_id}/events/stats",
        "operationId": "stats.getEventTimeseries",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Time window, e.g. '24h', '7d'. Omit for all time.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "interval",
            "in": "query",
            "description": "Bucket width in hours (default: 1, max: 24)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only events from this environment. Omit for every environment.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "release",
            "in": "query",
            "description": "Only events from this release. Omit for every release.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Time-bucketed error-event volume by severity",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EventTimeseriesPoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/feedback": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /api/projects/{project_id}/feedback\nLists user feedback with what each user submitted. Every feedback is an\nissue of category `feedback`; spam is a muted one.",
        "operationId": "feedback.list",
        "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, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "filter",
            "in": "query",
            "description": "open (the inbox, default), resolved, muted (spam) or all",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/IssueFilter"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "User feedback, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "A user feedback: its issue's state and what the user submitted\n(`contexts.feedback`, develop.sentry.dev/sdk/telemetry/feedbacks/).",
                        "required": [
                          "id",
                          "status",
                          "message",
                          "name",
                          "contact_email",
                          "url",
                          "associated_event_id",
                          "created_at",
                          "attachments"
                        ],
                        "properties": {
                          "associated_event_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "The SDK id of the error event it is about."
                          },
                          "attachments": {
                            "type": "array",
                            "items": {
                              "$ref": "#/components/schemas/AttachmentInfo"
                            },
                            "description": "Files sent with it, such as a screenshot."
                          },
                          "contact_email": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "The feedback's issue."
                          },
                          "message": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "status": {
                            "$ref": "#/components/schemas/IssueStatus"
                          },
                          "url": {
                            "type": "string",
                            "description": "The page it was sent from."
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/github": {
      "get": {
        "tags": [
          "GitHub"
        ],
        "summary": "GET /api/projects/{project_id}/github",
        "operationId": "github.getProjectRepository",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The project's repository, if any",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ProjectRepository"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "GitHub"
        ],
        "summary": "PUT /api/projects/{project_id}/github",
        "operationId": "github.putProjectRepository",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProjectRepository"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Repository saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectRepository"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "GitHub"
        ],
        "summary": "DELETE /api/projects/{project_id}/github",
        "operationId": "github.deleteProjectRepository",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Repository removed"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/github/codeowners": {
      "post": {
        "tags": [
          "GitHub"
        ],
        "summary": "POST /api/projects/{project_id}/github/codeowners: copies the repository's\nCODEOWNERS so ownership can be answered without asking GitHub each time.",
        "operationId": "github.syncCodeowners",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CODEOWNERS synced",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectRepository"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /api/projects/{project_id}/issues\nLists issues for a project with offset-based pagination",
        "operationId": "issues.list",
        "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, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort mode (default: last_seen)",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/IssueSort"
            }
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort order direction (default: desc)",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/SortOrder"
            }
          },
          {
            "name": "filter",
            "in": "query",
            "description": "Filter: open (not resolved, not muted), resolved, muted, all",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/IssueFilter"
            }
          },
          {
            "name": "category",
            "in": "query",
            "description": "Issue category: error (default) or feedback",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/IssueCategory"
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Free-text search across type, value, transaction, and culprit.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only issues seen in this environment, with that environment's first\nand last seen, event count, users and trend.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "release",
            "in": "query",
            "description": "Only issues that had an event in this release.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "level",
            "in": "query",
            "description": "Only these levels, comma-separated: `fatal,error`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "priority",
            "in": "query",
            "description": "Only these priorities, comma-separated: `high,medium`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "assigned",
            "in": "query",
            "description": "`none` for unassigned issues, or a user id.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "first_seen",
            "in": "query",
            "description": "Only issues first seen within this window: `24h`, `7d`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "last_seen",
            "in": "query",
            "description": "Only issues last seen within this window: `24h`, `7d`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "events_min",
            "in": "query",
            "description": "Only issues with at least this many events.",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "events_max",
            "in": "query",
            "description": "Only issues with at most this many events.",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of issues",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Response for API",
                        "required": [
                          "id",
                          "project_id",
                          "short_id",
                          "title",
                          "value",
                          "culprit",
                          "logger",
                          "first_seen",
                          "last_seen",
                          "event_count",
                          "level",
                          "platform",
                          "status",
                          "substatus",
                          "priority",
                          "assigned_to",
                          "assignee_type",
                          "issue_type",
                          "issue_category",
                          "first_release",
                          "last_release",
                          "status_details",
                          "is_resolved",
                          "is_muted"
                        ],
                        "properties": {
                          "assigned_to": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int32"
                          },
                          "assignee_type": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "culprit": {
                            "type": "string"
                          },
                          "event_count": {
                            "type": "integer",
                            "format": "int32"
                          },
                          "first_release": {
                            "type": "string"
                          },
                          "first_seen": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "has_seen": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "is_bookmarked": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "is_muted": {
                            "type": "boolean",
                            "description": "Deprecated: derived from `status`. See `is_resolved`."
                          },
                          "is_resolved": {
                            "type": "boolean",
                            "description": "Deprecated: derived from `status`. Kept for the legacy client/UI until\nthey migrate to `status`. Remove in the client/frontend phases of #165."
                          },
                          "is_subscribed": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "issue_category": {
                            "type": "string"
                          },
                          "issue_type": {
                            "type": "string"
                          },
                          "last_release": {
                            "type": "string"
                          },
                          "last_seen": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "level": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "logger": {
                            "type": "string"
                          },
                          "platform": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priority": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/IssuePriority"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "project_id": {
                            "type": "integer",
                            "format": "int32"
                          },
                          "short_id": {
                            "type": "string"
                          },
                          "status": {
                            "$ref": "#/components/schemas/IssueStatus"
                          },
                          "status_details": {
                            "type": "object"
                          },
                          "substatus": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "title": {
                            "type": "string"
                          },
                          "trend": {
                            "type": [
                              "array",
                              "null"
                            ],
                            "items": {
                              "type": "integer",
                              "format": "int64"
                            },
                            "description": "24 hourly buckets, oldest to newest. Only populated by the issue list\nendpoint."
                          },
                          "user_count": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int64",
                            "description": "Only populated by the issue list endpoint (bulk-computed per page)."
                          },
                          "user_report_count": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int64",
                            "description": "Only populated by the single-issue GET endpoint."
                          },
                          "value": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Issues"
        ],
        "summary": "PUT /api/projects/{project_id}/issues  (bulk mutate)",
        "operationId": "issues.bulkUpdate",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkUpdateIssues"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Number of issues updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkUpdateResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Issues"
        ],
        "summary": "DELETE /api/projects/{project_id}/issues  (bulk delete by ids or filter)",
        "operationId": "issues.bulkDelete",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkDeleteIssues"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Number of issues deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkDeleteResponse"
                }
              }
            }
          },
          "400": {
            "description": "Neither or both of ids and filter given",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /api/projects/{project_id}/issues/{issue_id}\nGets a single issue by ID",
        "operationId": "issues.get",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Issue details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Issues"
        ],
        "summary": "DELETE /api/projects/{project_id}/issues/{issue_id}\nHard-deletes an issue and all associated events",
        "operationId": "issues.delete",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Issue deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Issues"
        ],
        "summary": "PATCH /api/projects/{project_id}/issues/{issue_id}\nUpdates issue state (resolve, mute, etc.)",
        "operationId": "issues.update",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateIssueState"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Issue updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/activity": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /{issue_id}/activity — chronological activity log (incl. comments).",
        "operationId": "issues.getActivity",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Activity log (status changes, comments, …)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ActivityEntry"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/aggregates": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /api/projects/{project_id}/issues/{issue_id}/aggregates\nReturns the unique user count and top tags for the issue.",
        "operationId": "issues.getAggregates",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Unique user count and top tags",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueAggregates"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/bookmark": {
      "put": {
        "tags": [
          "Issues"
        ],
        "summary": "PUT /{issue_id}/bookmark — set/clear the per-user bookmark.",
        "operationId": "issues.setBookmark",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToggleRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Updated bookmark state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookmarkResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/comments": {
      "post": {
        "tags": [
          "Issues"
        ],
        "summary": "POST /{issue_id}/comments — add a note.",
        "operationId": "issues.createComment",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Comment added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivityEntry"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/events": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "GET /api/projects/{project_id}/issues/{issue_id}/events\nLists events for an issue with cursor-based pagination",
        "operationId": "events.list",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort order direction (default: desc = newest first)",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/SortOrder"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Pagination cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only events in this environment.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated event list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Paginated response wrapper (cursor-based)",
                  "required": [
                    "items",
                    "has_more"
                  ],
                  "properties": {
                    "has_more": {
                      "type": "boolean"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Response for API (list view)",
                        "required": [
                          "id",
                          "event_id",
                          "issue_id",
                          "title",
                          "timestamp",
                          "level",
                          "platform",
                          "release",
                          "environment",
                          "event_type"
                        ],
                        "properties": {
                          "environment": {
                            "type": "string"
                          },
                          "event_id": {
                            "type": "string",
                            "description": "Sentry event ID: 32 hex digits, not necessarily an RFC 4122 UUID."
                          },
                          "event_type": {
                            "type": "string"
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "issue_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "level": {
                            "type": "string"
                          },
                          "platform": {
                            "type": "string"
                          },
                          "release": {
                            "type": "string"
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "title": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/events/{event_id}": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "GET /api/projects/{project_id}/issues/{issue_id}/events/{event_id}\nGets a single event with full data",
        "operationId": "events.get",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "description": "Event ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Full event detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/events/{event_id}/attachments": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "GET /api/projects/{project_id}/issues/{issue_id}/events/{event_id}/attachments\nLists the files sent with an event, such as a feedback's screenshot.",
        "operationId": "events.listAttachments",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "description": "Event ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The files sent with the event, without their bytes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AttachmentInfo"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/github": {
      "get": {
        "tags": [
          "GitHub"
        ],
        "summary": "GET /api/projects/{project_id}/issues/{issue_id}/github: the issue's links,\nthe commits that may have caused it, and who owns its culprit file.",
        "operationId": "github.issue",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Links, suspect commits and owners",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueGitHub"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/github/draft": {
      "get": {
        "tags": [
          "GitHub"
        ],
        "summary": "GET .../github/draft: what creating a GitHub issue sends by default, with\nthe templates applied, for the person to edit first.",
        "operationId": "github.issueDraft",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Title, body and labels to start from",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitHubIssueDraft"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/github/issues": {
      "post": {
        "tags": [
          "GitHub"
        ],
        "summary": "POST .../github/issues: opens a GitHub issue and links it.",
        "operationId": "github.createIssue",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateGitHubIssue"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "GitHub issue created and linked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueLink"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/github/links": {
      "post": {
        "tags": [
          "GitHub"
        ],
        "summary": "POST .../github/links: links an existing GitHub issue or pull request.",
        "operationId": "github.linkIssue",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkGitHubIssue"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "GitHub issue linked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueLink"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/github/links/{link_id}": {
      "delete": {
        "tags": [
          "GitHub"
        ],
        "summary": "DELETE .../github/links/{link_id}",
        "operationId": "github.unlinkIssue",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "link_id",
            "in": "path",
            "description": "Link ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Link removed"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/hashes": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /api/projects/{project_id}/issues/{issue_id}/hashes\nLists the grouping hashes that map to an issue.",
        "operationId": "issues.getHashes",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Grouping hashes mapped to the issue",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Grouping"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/seen": {
      "post": {
        "tags": [
          "Issues"
        ],
        "summary": "POST /{issue_id}/seen — mark the issue as seen by the current user.",
        "operationId": "issues.markSeen",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Issue marked as seen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SeenResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/stats": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /{issue_id}/stats?window=24h|30d — zero-filled event-count timeseries.",
        "operationId": "issues.getStats",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "window",
            "in": "query",
            "description": "Time window (default: 24h)",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/IssueStatsWindow"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Zero-filled event-count timeseries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueStatsResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/subscription": {
      "put": {
        "tags": [
          "Issues"
        ],
        "summary": "PUT /{issue_id}/subscription — set/clear the per-user subscription.",
        "operationId": "issues.setSubscription",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToggleRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Updated subscription state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/tags/{key}": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /api/projects/{project_id}/issues/{issue_id}/tags/{key}\nLists the distinct values (with counts) for a tag key across the issue.",
        "operationId": "issues.getTagValues",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "key",
            "in": "path",
            "description": "Tag key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Distinct values for the tag key, one entry per value (Sentry-compatible: a bare list, not wrapped)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/IssueTagValue"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/issues/{issue_id}/user-reports": {
      "get": {
        "tags": [
          "Issues"
        ],
        "summary": "GET /{issue_id}/user-reports — list user feedback for an issue.",
        "operationId": "issues.listUserReports",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "User feedback reports for the issue, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "A user feedback report attached to a project/issue/event.",
                        "required": [
                          "id",
                          "project_id",
                          "issue_id",
                          "event_id",
                          "name",
                          "email",
                          "comments",
                          "created_at"
                        ],
                        "properties": {
                          "comments": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "email": {
                            "type": "string"
                          },
                          "event_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "issue_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "project_id": {
                            "type": "integer",
                            "format": "int32"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Issues"
        ],
        "summary": "POST /{issue_id}/user-reports — attach user feedback to an issue.",
        "operationId": "issues.createUserReport",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserReportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "User feedback attached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserReport"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/logs": {
      "get": {
        "tags": [
          "Logs"
        ],
        "summary": "GET /api/projects/{project_id}/logs\nLists logs for a project with offset-based pagination (newest first by\nlog timestamp), optionally filtered by level, trace id, message and window.",
        "operationId": "logs.list",
        "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, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          },
          {
            "name": "level",
            "in": "query",
            "description": "Filter by log level (trace/debug/info/warn/error/fatal).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "trace_id",
            "in": "query",
            "description": "Filter by trace id.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "query",
            "in": "query",
            "description": "Only the logs whose message contains this, ignoring case.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Only this window (`24h`, `7d`, `14d`...); all time if absent.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated log list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Response model for a single stored log in the list view.",
                        "required": [
                          "id",
                          "trace_id",
                          "span_id",
                          "level",
                          "severity_number",
                          "body",
                          "attributes",
                          "timestamp",
                          "ingested_at"
                        ],
                        "properties": {
                          "attributes": {
                            "type": "object",
                            "description": "Typed attribute map, as received."
                          },
                          "body": {
                            "type": "string"
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "ingested_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "level": {
                            "type": "string"
                          },
                          "severity_number": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int32",
                            "description": "OTel severity number (1=trace … 21=fatal). None for unknown levels."
                          },
                          "span_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "trace_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/logs/volume": {
      "get": {
        "tags": [
          "Logs"
        ],
        "summary": "GET /api/projects/{project_id}/logs/volume\nCounts a project's logs per level over time, with the list's filters.",
        "operationId": "logs.volume",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "level",
            "in": "query",
            "description": "Filter by log level (trace/debug/info/warn/error/fatal).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "trace_id",
            "in": "query",
            "description": "Filter by trace id.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "query",
            "in": "query",
            "description": "Only the logs whose message contains this, ignoring case.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Only this window (`24h`, `7d`, `14d`...); since the oldest log if absent.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Log counts per level, bucket by bucket",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LogVolumePoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/logs/{log_id}": {
      "get": {
        "tags": [
          "Logs"
        ],
        "summary": "GET /api/projects/{project_id}/logs/{log_id}\nReturns one of a project's logs, wherever it falls in the list.",
        "operationId": "logs.get",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "log_id",
            "in": "path",
            "description": "Log ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The log",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LogResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/members": {
      "get": {
        "tags": [
          "Members"
        ],
        "summary": "Lists everyone holding a role on the project, with those roles; personal permissions are not roles.",
        "operationId": "members.list",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProjectMember"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing project-members:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Members"
        ],
        "summary": "Sets the roles a user holds on the project.",
        "operationId": "members.upsert",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetProjectMember"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Project members now",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProjectMember"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unknown role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing project-members:update, own membership, or a role beyond the caller's",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project or user not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/members/candidates": {
      "get": {
        "tags": [
          "Members"
        ],
        "summary": "Lists the people and the roles the caller can give on the project, so it takes neither `users:read` nor `roles:read` to manage its members.",
        "operationId": "members.candidates",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "People and roles the caller can give",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberCandidates"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing project-members:update",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/members/{user_id}": {
      "delete": {
        "tags": [
          "Members"
        ],
        "summary": "Removes the roles a user holds on this project; roles on all projects and personal permissions stay.",
        "operationId": "members.remove",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "path",
            "description": "User ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Removed"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing project-members:update, own membership, or a role beyond the caller's",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/monitor-stats": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "GET /api/projects/{project_id}/monitor-stats\nCounts the check-ins of a project's monitors by status over a window, bucket by bucket.",
        "operationId": "monitors.stats",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "The window (`24h`, `7d`, `30d`...); the last day if absent.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "slug",
            "in": "query",
            "description": "Only this monitor.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Each monitor environment's check-ins by status, in sixty buckets on one axis",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MonitorEnvironmentStats"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/monitors": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "GET /api/projects/{project_id}/monitors",
        "operationId": "monitors.list",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Every cron monitor of the project, with its environments and recent check-ins",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MonitorResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Monitors"
        ],
        "summary": "POST /api/projects/{project_id}/monitors",
        "operationId": "monitors.create",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMonitor"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid name or config",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Slug already taken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/monitors/{slug}": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "GET /api/projects/{project_id}/monitors/{slug}",
        "operationId": "monitors.get",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "description": "Monitor slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The monitor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Monitors"
        ],
        "summary": "PUT /api/projects/{project_id}/monitors/{slug}",
        "operationId": "monitors.update",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "description": "Monitor slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMonitor"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid name or config",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Monitors"
        ],
        "summary": "DELETE /api/projects/{project_id}/monitors/{slug}",
        "operationId": "monitors.delete",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "description": "Monitor slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted with its check-ins; its issues stay"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/monitors/{slug}/checkins": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "GET /api/projects/{project_id}/monitors/{slug}/checkins",
        "operationId": "monitors.listCheckins",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "description": "Monitor slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 50, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only check-ins from this environment.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Check-ins, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "One check-in, as the dashboard reads it.",
                        "required": [
                          "id",
                          "environment",
                          "status",
                          "duration_ms",
                          "date_added",
                          "date_updated",
                          "expected_time"
                        ],
                        "properties": {
                          "date_added": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "date_updated": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "duration_ms": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int64"
                          },
                          "environment": {
                            "type": "string"
                          },
                          "expected_time": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "status": {
                            "$ref": "#/components/schemas/CheckInStatus"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/releases": {
      "get": {
        "tags": [
          "Releases"
        ],
        "summary": "Lists a project's releases, newest first, with the events, new issues,\nenvironments and session health of each.",
        "operationId": "releases.list",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only the releases seen in this environment, and count only it",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Count only this window (24h, 7d, 14d...); all time if absent",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "query",
            "in": "query",
            "description": "Only the versions containing this text, ignoring case",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Releases, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "One release as the releases page reads it: its record, if CI created\none, and what it brought -- events, new issues, environments and session\nhealth -- the shape of Sentry's release list with `health=1`.\n\nCounts and rates cover the asked window and environment; the dates do not,\nso a release keeps its age however narrow the window.",
                        "required": [
                          "version",
                          "date_created",
                          "date_released",
                          "ref",
                          "url",
                          "first_event",
                          "last_event",
                          "event_count",
                          "new_issues",
                          "environments",
                          "sessions",
                          "crashed",
                          "crash_free_sessions",
                          "crash_free_users",
                          "adoption"
                        ],
                        "properties": {
                          "adoption": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double",
                            "description": "Its share of every release's sessions in the window, 0 to 1."
                          },
                          "crash_free_sessions": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double"
                          },
                          "crash_free_users": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double"
                          },
                          "crashed": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "date_created": {
                            "type": "string",
                            "format": "date-time",
                            "description": "The record's, else the first time the release was seen."
                          },
                          "date_released": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "environments": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Where it ran, from its events and its sessions."
                          },
                          "event_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "first_event": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "last_event": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "new_issues": {
                            "type": "integer",
                            "format": "int64",
                            "description": "Error issues first seen in it."
                          },
                          "ref": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sessions": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "url": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "version": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Project not found"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/releases/{release}": {
      "get": {
        "tags": [
          "Releases"
        ],
        "summary": "Gets one release with its events, new issues, environments and session\nhealth.",
        "operationId": "releases.get",
        "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"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Count only this environment",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Count only this window; all time if absent",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The release",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "No such release in this project"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/releases/{release}/new-issues": {
      "get": {
        "tags": [
          "Releases"
        ],
        "summary": "GET /api/projects/{project_id}/releases/{release}/new-issues",
        "operationId": "releases.newIssues",
        "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"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max issues to return (default: 10, max: 50)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Issues first seen in this release, most recent first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/IssueResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/sessions/stats": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "GET /api/projects/{project_id}/sessions/stats",
        "operationId": "sessions.getStats",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Time window in hours (default: 24).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "release",
            "in": "query",
            "description": "Scope to a single release (all environments). When omitted, every\nrelease in the project is returned.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated per-release health stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Per-release health row returned by the stats endpoint.",
                        "required": [
                          "release",
                          "environment",
                          "total",
                          "errored",
                          "crashed",
                          "abnormal",
                          "healthy",
                          "crash_free_sessions_rate",
                          "crash_free_users_rate"
                        ],
                        "properties": {
                          "abnormal": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "crash_free_sessions_rate": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double"
                          },
                          "crash_free_users_rate": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double"
                          },
                          "crashed": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "environment": {
                            "type": "string"
                          },
                          "errored": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "healthy": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "release": {
                            "type": "string"
                          },
                          "total": {
                            "type": "integer",
                            "format": "int64"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/sessions/summary": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "GET /api/projects/{project_id}/sessions/summary",
        "operationId": "sessions.getSummary",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Time window, e.g. '24h', '7d' (default: 24h)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only sessions from this environment. Omit for every environment.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "release",
            "in": "query",
            "description": "Only sessions from this release. Omit for every release.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project-wide session health summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/sessions/timeseries": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "GET /api/projects/{project_id}/sessions/timeseries",
        "operationId": "sessions.getTimeseries",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Time window, e.g. '24h', '7d' (default: 24h)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "interval",
            "in": "query",
            "description": "Bucket width in hours (default: 1, max: 24)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only sessions from this environment. Omit for every environment.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "release",
            "in": "query",
            "description": "Only sessions from this release. Omit for every release.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Time-bucketed session trend, project-wide",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SessionTimeseriesPoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/spans": {
      "get": {
        "tags": [
          "Spans"
        ],
        "summary": "GET /api/projects/{project_id}/spans\nLists spans for a project with offset-based pagination (newest by\nstart_timestamp first), optionally filtered by op/status/trace_id.\nReturns spans regardless of origin — standalone or extracted from a\ntransaction — since both are stored in the same table.",
        "operationId": "spans.list",
        "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, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          },
          {
            "name": "op",
            "in": "query",
            "description": "Filter by span operation, e.g. `http.client`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by span status.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "trace_id",
            "in": "query",
            "description": "Filter by trace id — matches spans regardless of origin (standalone\nor extracted from a transaction), since both share this table.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "operation_type",
            "in": "query",
            "description": "Filter by gen_ai.operation.type\n(`agent`/`tool`/`handoff`/`ai_client`/`other`).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated span list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "A single indexed span — extracted from a transaction, OR standalone\n(Sentry \"span\" item type). Both origins write into the same `spans`\ntable, so `transaction_id` is the only thing that distinguishes them.",
                        "required": [
                          "id",
                          "transaction_id",
                          "span_id",
                          "trace_id",
                          "parent_span_id",
                          "op",
                          "description",
                          "status",
                          "start_timestamp",
                          "timestamp",
                          "duration_ms",
                          "exclusive_time_ms",
                          "is_segment",
                          "segment_id",
                          "platform",
                          "release",
                          "environment",
                          "gen_ai_operation_type",
                          "gen_ai_agent_name",
                          "gen_ai_request_model",
                          "gen_ai_response_model",
                          "gen_ai_tool_name",
                          "gen_ai_conversation_id",
                          "gen_ai_usage_input_tokens",
                          "gen_ai_usage_output_tokens",
                          "gen_ai_usage_total_tokens"
                        ],
                        "properties": {
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "duration_ms": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double",
                            "description": "Duration in milliseconds (timestamp - start_timestamp)."
                          },
                          "environment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "exclusive_time_ms": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double",
                            "description": "Relay's exclusive (self) time in milliseconds, if provided by the SDK."
                          },
                          "gen_ai_agent_name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "gen_ai_conversation_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "gen_ai_operation_type": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "gen_ai.* denormalized fields (story-ai-agent-monitoring.md, GH #180).\nAll `None` unless the span was recognized as an AI span."
                          },
                          "gen_ai_request_model": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "gen_ai_response_model": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "gen_ai_tool_name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "gen_ai_usage_input_tokens": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double"
                          },
                          "gen_ai_usage_output_tokens": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double"
                          },
                          "gen_ai_usage_total_tokens": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double"
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "is_segment": {
                            "type": "boolean"
                          },
                          "op": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "parent_span_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "platform": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Set for every span. A standalone span reports its own; a\ntransaction-embedded one is stamped with its parent transaction's at\nwrite time, rather than being left NULL to be recovered by a JOIN —\nthe agents dashboard filters `spans` directly and a NULL would drop\nthe row from an environment-filtered view."
                          },
                          "release": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "segment_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "span_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "start_timestamp": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "timestamp": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "trace_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "transaction_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid",
                            "description": "The parent transaction, if this span was extracted from one.\n`None` for a standalone span."
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/spans/{span_id}": {
      "get": {
        "tags": [
          "Spans"
        ],
        "summary": "GET /api/projects/{project_id}/spans/{span_id}\nReturns one span together with its attributes and tags — the `gen_ai.*`\npayload (prompts, responses, tool arguments and results) that the list\nresponse deliberately omits, since `spans.data` is untrimmed and a whole\ntrace's worth of it would dwarf the waterfall it is drawn from.",
        "operationId": "spans.get",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "span_id",
            "in": "path",
            "description": "Span row ID (the `id` field of a span list item, not the SDK's 16-hex span_id)",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Span with its full attribute bag",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SpanDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/stats/summary": {
      "get": {
        "tags": [
          "Stats"
        ],
        "summary": "GET /api/projects/{project_id}/stats/summary",
        "operationId": "stats.getSummary",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Time window, e.g. '24h', '7d'. Omit for all time.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only events, and issues seen, in this environment. Omit for every environment.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "release",
            "in": "query",
            "description": "Only events, and issues seen, in this release. Omit for every release.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project counters with previous-period comparison",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectStatsSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/transactions": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "GET /api/projects/{project_id}/transactions\nLists transactions for a project with offset-based pagination (newest first).",
        "operationId": "transactions.list",
        "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, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Filter by exact transaction name (lists one group's samples).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "op",
            "in": "query",
            "description": "Filter by trace operation (contexts.trace.op), e.g. `http.server`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by trace status (contexts.trace.status), e.g. `ok`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Filter by environment.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "release",
            "in": "query",
            "description": "Filter by release.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Only this window (`24h`, `7d`, `14d`...); all time if absent.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "`slowest` for the longest first; newest first otherwise.",
            "required": false,
            "schema": {
              "oneOf": [
                {
                  "type": "string",
                  "description": "The order of a transaction list.",
                  "enum": [
                    "recent",
                    "slowest"
                  ]
                },
                {
                  "type": "null"
                }
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated transaction list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Response model for a single transaction in the list view",
                        "required": [
                          "id",
                          "event_id",
                          "transaction_name",
                          "timestamp",
                          "start_timestamp",
                          "duration_ms",
                          "platform",
                          "environment",
                          "release",
                          "ingested_at",
                          "status"
                        ],
                        "properties": {
                          "duration_ms": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "format": "double",
                            "description": "Duration in milliseconds (timestamp - start_timestamp). None if start_timestamp is missing."
                          },
                          "environment": {
                            "type": "string"
                          },
                          "event_id": {
                            "type": "string",
                            "description": "Sentry event ID: 32 hex digits, not necessarily an RFC 4122 UUID."
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "ingested_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "platform": {
                            "type": "string"
                          },
                          "release": {
                            "type": "string"
                          },
                          "start_timestamp": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "status": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Trace status (`ok`, `internal_error`...), if the SDK sent one."
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "transaction_name": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/transactions/stats": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "GET /api/projects/{project_id}/transactions/stats\nReturns paginated aggregate performance stats (count, time spent, p50/p95/p99\nlatency, failure rate) grouped by transaction name + op, the most time spent\nfirst unless `sort` asks otherwise.",
        "operationId": "transactions.getStats",
        "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, default: 1)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 20, max: 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "maximum": 100,
              "minimum": 1
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only this environment.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Only this window (`24h`, `7d`, `14d`...); all time if absent.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "query",
            "in": "query",
            "description": "Only the endpoints whose name contains this, ignoring case.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "How to rank them; most time spent in all by default.",
            "required": false,
            "schema": {
              "type": "string",
              "description": "How the endpoints are ranked.",
              "enum": [
                "time_spent",
                "count",
                "avg",
                "failure_rate"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated aggregate latency/throughput/failure stats per (transaction, op)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Offset-based paginated response wrapper",
                  "required": [
                    "items",
                    "total_count",
                    "page",
                    "per_page",
                    "total_pages"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Aggregate performance stats for one (transaction_name, op) group.\nPowers the performance overview: throughput + latency percentiles +\nfailure rate per transaction. Percentiles are continuous (linear\ninterpolation, matching Postgres `percentile_cont`).",
                        "required": [
                          "transaction_name",
                          "op",
                          "count",
                          "p50_ms",
                          "p95_ms",
                          "p99_ms",
                          "failure_rate",
                          "avg_ms",
                          "total_ms",
                          "time_share",
                          "last_seen"
                        ],
                        "properties": {
                          "avg_ms": {
                            "type": "number",
                            "format": "double"
                          },
                          "count": {
                            "type": "integer",
                            "format": "int64",
                            "description": "Number of transactions in this group."
                          },
                          "failure_rate": {
                            "type": "number",
                            "format": "double",
                            "description": "Fraction (0.0–1.0) of transactions whose trace status is set and not \"ok\"."
                          },
                          "last_seen": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "op": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "p50_ms": {
                            "type": "number",
                            "format": "double"
                          },
                          "p95_ms": {
                            "type": "number",
                            "format": "double"
                          },
                          "p99_ms": {
                            "type": "number",
                            "format": "double"
                          },
                          "time_share": {
                            "type": "number",
                            "format": "double",
                            "description": "Its share, 0 to 1, of the time every endpoint in the same read takes."
                          },
                          "total_ms": {
                            "type": "number",
                            "format": "double",
                            "description": "Every sample's duration added up: how much time the endpoint takes in all."
                          },
                          "transaction_name": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "per_page": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_pages": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/transactions/stats/group": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "GET /api/projects/{project_id}/transactions/stats/group?name=&op=\nReturns the aggregate stats for a single transaction group — a direct lookup\nso the summary header works regardless of how many groups the project has.",
        "operationId": "transactions.getStatGroup",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Exact transaction name of the group.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "op",
            "in": "query",
            "description": "Trace operation of the group (omit for groups with no op).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only this environment.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Only this window (`24h`, `7d`, `14d`...); all time if absent.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Aggregate stats for one (transaction, op) group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionStatsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Group not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/transactions/stats/group/timeseries": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "Returns one endpoint's trend over the window, every bucket present:\nhow often it ran and failed, and its p50 and p95. Without a window, back\nto its oldest call and never less than the last 24 hours, which is also\nwhat an endpoint with no calls gets.",
        "operationId": "transactions.getStatGroupTimeseries",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Exact transaction name of the group.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "op",
            "in": "query",
            "description": "Trace operation of the group (omit for groups with no op).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "environment",
            "in": "query",
            "description": "Only this environment.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Only this window (`24h`, `7d`, `14d`...); all time if absent.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint's runs, failures, p50 and p95 per bucket, oldest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TransactionTimeseriesPoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/transactions/{transaction_id}": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "GET /api/projects/{project_id}/transactions/{transaction_id}\nReturns a single transaction with its full Sentry payload (spans, contexts,\nmeasurements, tags) for the performance detail view.",
        "operationId": "transactions.get",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "transaction_id",
            "in": "path",
            "description": "Transaction ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Full transaction detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/projects/{project_id}/transactions/{transaction_id}/spans": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "GET /api/projects/{project_id}/transactions/{transaction_id}/spans\nReturns the indexed spans extracted from a transaction, ordered for the\nwaterfall view (by start_timestamp ascending).",
        "operationId": "transactions.getSpans",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "description": "Project ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "transaction_id",
            "in": "path",
            "description": "Transaction ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Indexed spans for the transaction (waterfall order)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "description": "A single indexed span — extracted from a transaction, OR standalone\n(Sentry \"span\" item type). Both origins write into the same `spans`\ntable, so `transaction_id` is the only thing that distinguishes them.",
                    "required": [
                      "id",
                      "transaction_id",
                      "span_id",
                      "trace_id",
                      "parent_span_id",
                      "op",
                      "description",
                      "status",
                      "start_timestamp",
                      "timestamp",
                      "duration_ms",
                      "exclusive_time_ms",
                      "is_segment",
                      "segment_id",
                      "platform",
                      "release",
                      "environment",
                      "gen_ai_operation_type",
                      "gen_ai_agent_name",
                      "gen_ai_request_model",
                      "gen_ai_response_model",
                      "gen_ai_tool_name",
                      "gen_ai_conversation_id",
                      "gen_ai_usage_input_tokens",
                      "gen_ai_usage_output_tokens",
                      "gen_ai_usage_total_tokens"
                    ],
                    "properties": {
                      "description": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_ms": {
                        "type": [
                          "number",
                          "null"
                        ],
                        "format": "double",
                        "description": "Duration in milliseconds (timestamp - start_timestamp)."
                      },
                      "environment": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "exclusive_time_ms": {
                        "type": [
                          "number",
                          "null"
                        ],
                        "format": "double",
                        "description": "Relay's exclusive (self) time in milliseconds, if provided by the SDK."
                      },
                      "gen_ai_agent_name": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "gen_ai_conversation_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "gen_ai_operation_type": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "description": "gen_ai.* denormalized fields (story-ai-agent-monitoring.md, GH #180).\nAll `None` unless the span was recognized as an AI span."
                      },
                      "gen_ai_request_model": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "gen_ai_response_model": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "gen_ai_tool_name": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "gen_ai_usage_input_tokens": {
                        "type": [
                          "number",
                          "null"
                        ],
                        "format": "double"
                      },
                      "gen_ai_usage_output_tokens": {
                        "type": [
                          "number",
                          "null"
                        ],
                        "format": "double"
                      },
                      "gen_ai_usage_total_tokens": {
                        "type": [
                          "number",
                          "null"
                        ],
                        "format": "double"
                      },
                      "id": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "is_segment": {
                        "type": "boolean"
                      },
                      "op": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "parent_span_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "platform": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "description": "Set for every span. A standalone span reports its own; a\ntransaction-embedded one is stamped with its parent transaction's at\nwrite time, rather than being left NULL to be recovered by a JOIN —\nthe agents dashboard filters `spans` directly and a NULL would drop\nthe row from an environment-filtered view."
                      },
                      "release": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "segment_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "span_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "start_timestamp": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "timestamp": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "trace_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "transaction_id": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "uuid",
                        "description": "The parent transaction, if this span was extracted from one.\n`None` for a standalone span."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/rate-limits": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "GET /api/rate-limits - What a project without limits of its own follows",
        "operationId": "projects.getRateLimits",
        "responses": {
          "200": {
            "description": "The server's per-project limits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RateLimitsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/roles": {
      "get": {
        "tags": [
          "Access"
        ],
        "summary": "Lists every role with its permissions and how often it is assigned.",
        "operationId": "roles.list",
        "responses": {
          "200": {
            "description": "Every role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Role"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing roles:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Access"
        ],
        "summary": "Creates a role from permissions the caller holds themselves.",
        "operationId": "roles.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Role"
                }
              }
            }
          },
          "400": {
            "description": "Invalid role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing roles:create, or a permission the caller lacks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Name taken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/roles/{id}": {
      "put": {
        "tags": [
          "Access"
        ],
        "summary": "Replaces a role's name, description and permissions.",
        "description": "The caller must hold both the permissions being added and those being\nremoved, so nobody strips a role of something they could not give back.",
        "operationId": "roles.update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Role ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Role"
                }
              }
            }
          },
          "400": {
            "description": "Invalid role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing roles:update, or a permission the caller lacks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No such role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Name taken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Access"
        ],
        "summary": "Deletes a role nobody holds.",
        "operationId": "roles.delete",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Role ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing roles:delete",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No such role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Role still assigned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/schedules/preview": {
      "post": {
        "tags": [
          "Schedules"
        ],
        "summary": "POST /api/schedules/preview",
        "description": "Validates a schedule and lists its next five runs from now, so no client\never parses a crontab itself.",
        "operationId": "schedules.preview",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewSchedule"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The next five runs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SchedulePreview"
                }
              }
            }
          },
          "400": {
            "description": "Invalid schedule or timezone",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/settings/mcp": {
      "get": {
        "tags": [
          "Settings"
        ],
        "summary": "Whether the MCP endpoint at `/mcp` is on. Open to every member: it is what\nthey point their own assistant at.",
        "operationId": "settings.getMcp",
        "responses": {
          "200": {
            "description": "Whether the MCP endpoint is on, and its URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpStatus"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Settings"
        ],
        "summary": "Turns the MCP endpoint at `/mcp` on or off (needs `mcp:update`).",
        "operationId": "settings.updateMcp",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/McpSettings"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The MCP endpoint's new state, and its URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpStatus"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing mcp:update",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/age": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "GET /api/storage/age — rows per age bucket, per project and kind.",
        "operationId": "storage.getAge",
        "responses": {
          "200": {
            "description": "How long ago each project's data arrived, per kind",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageAge"
                }
              }
            }
          },
          "403": {
            "description": "Missing storage:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/cleanup": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "POST /api/storage/cleanup — starts deleting old data and the issues it\nempties. Returns at once: the purge runs detached, in batches, and\n`GET /api/storage/cleanup/status` reports its progress.",
        "operationId": "storage.executeCleanup",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CleanupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Cleanup started in the background; poll its status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CleanupStatus"
                }
              }
            }
          },
          "400": {
            "description": "Invalid retention window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A cleanup is already running",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/cleanup/preview": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "POST /api/storage/cleanup/preview — dry-run count, mutates nothing.",
        "operationId": "storage.previewCleanup",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CleanupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Dry-run: rows a cleanup would remove",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CleanupCounts"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/cleanup/status": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "GET /api/storage/cleanup/status — progress of the running cleanup, or the\noutcome of the last one.",
        "operationId": "storage.getCleanupStatus",
        "responses": {
          "200": {
            "description": "The current or last cleanup and the rows it removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CleanupStatus"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/compaction": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "GET /api/storage/compaction — whether the database file shrinks when data\nis deleted, and the disk a one-off compaction needs.",
        "operationId": "storage.getCompaction",
        "responses": {
          "200": {
            "description": "Whether the SQLite file gives freed space back, and what compacting it takes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Compaction"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "POST /api/storage/compaction — rewrites a SQLite file created before\nincremental mode, so it gives freed space back from then on. Writes wait\nwhile it runs; follow it with `GET /api/storage/cleanup/status`.",
        "operationId": "storage.compact",
        "responses": {
          "202": {
            "description": "Compaction started in the background; poll the cleanup status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CleanupStatus"
                }
              }
            }
          },
          "400": {
            "description": "Nothing to compact, or not enough free disk",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A cleanup is already running",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/projects": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "GET /api/storage/projects — per-project counts and estimated weight.",
        "operationId": "storage.getProjects",
        "responses": {
          "200": {
            "description": "Per-project storage breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "description": "Per-project storage breakdown, one row per project (including empty ones).\n\nCounts are exact. `estimated_bytes` estimates the JSON payload length this\nproject holds across events, transactions, spans and logs: a sample of its\nnewest rows per table (spans, which have no ingest time, are sampled in no\nparticular order), scaled by the row count. It is exact for a project with\nno more rows than the sample.",
                    "required": [
                      "project_id",
                      "project_name",
                      "events_count",
                      "transactions_count",
                      "spans_count",
                      "logs_count",
                      "source_maps_count",
                      "estimated_bytes",
                      "events_bytes",
                      "transactions_bytes",
                      "logs_bytes"
                    ],
                    "properties": {
                      "estimated_bytes": {
                        "type": "integer",
                        "format": "int64",
                        "description": "`events_bytes + transactions_bytes + logs_bytes`."
                      },
                      "events_bytes": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Events with their attachments."
                      },
                      "events_count": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "logs_bytes": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "logs_count": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "project_id": {
                        "type": "integer",
                        "format": "int32"
                      },
                      "project_name": {
                        "type": "string"
                      },
                      "source_maps_count": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "spans_count": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "transactions_bytes": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Transactions with their spans."
                      },
                      "transactions_count": {
                        "type": "integer",
                        "format": "int64"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/retention": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "GET /api/storage/retention",
        "operationId": "storage.getRetention",
        "responses": {
          "200": {
            "description": "Retention settings, next cleanup and last cleanup",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetentionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing storage:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Storage"
        ],
        "summary": "PUT /api/storage/retention",
        "operationId": "storage.updateRetention",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RetentionSettings"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Saved; the new schedule applies within a minute",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetentionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Settings that cannot run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing storage:update",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/retention/preview": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "POST /api/storage/retention/preview — what saving these settings would\ndelete on the next cleanup, without saving or deleting anything.",
        "operationId": "storage.previewRetention",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RetentionSettings"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Dry-run: rows enforcing these settings now would remove",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CleanupCounts"
                }
              }
            }
          },
          "400": {
            "description": "Settings that cannot run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing storage:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/retention/run": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "POST /api/storage/retention/run — enforces the saved retention now,\nwithout waiting for the schedule. Follow it with the cleanup status.",
        "operationId": "storage.runRetention",
        "responses": {
          "202": {
            "description": "Cleanup started in the background; poll its status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CleanupStatus"
                }
              }
            }
          },
          "400": {
            "description": "Everything is kept forever: nothing to clean up",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing storage:delete",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A cleanup is already running",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/source-maps/gc": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "POST /api/storage/source-maps/gc — delete orphaned source maps (DB + disk).",
        "operationId": "storage.gcSourceMaps",
        "responses": {
          "200": {
            "description": "Orphaned source maps removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SourceMapGcResult"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/source-maps/gc/preview": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "POST /api/storage/source-maps/gc/preview — dry-run orphan count, deletes nothing.",
        "operationId": "storage.previewSourceMapGc",
        "responses": {
          "200": {
            "description": "Dry-run: orphaned source maps a GC would remove",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SourceMapGcResult"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/storage/summary": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "GET /api/storage/summary — row counts, DB size, and source-map weight.",
        "operationId": "storage.getSummary",
        "responses": {
          "200": {
            "description": "Instance-wide storage summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageSummary"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/team": {
      "get": {
        "tags": [
          "Team"
        ],
        "summary": "GET /api/team — list all users (needs `users:read`)",
        "operationId": "team.list",
        "responses": {
          "200": {
            "description": "List of team members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TeamMemberResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/team/{user_id}": {
      "delete": {
        "tags": [
          "Team"
        ],
        "summary": "DELETE /api/team/{user_id} — remove a user from the instance (needs `users:delete`)",
        "operationId": "team.deleteUser",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "description": "User ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "User deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "User not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Cannot delete the last admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/team/{user_id}/role": {
      "patch": {
        "tags": [
          "Team"
        ],
        "summary": "PATCH /api/team/{user_id}/role — change a user's global role (needs `users:update`)",
        "operationId": "team.updateRole",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "description": "User ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateUserRole"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Role updated"
          },
          "400": {
            "description": "Invalid role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "User not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Cannot demote the last admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/telemetry/preview": {
      "get": {
        "tags": [
          "Telemetry"
        ],
        "summary": "GET /api/telemetry/preview",
        "operationId": "telemetry.preview",
        "responses": {
          "200": {
            "description": "What the next heartbeat would carry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TelemetryPreview"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/tokens": {
      "get": {
        "tags": [
          "Tokens"
        ],
        "summary": "GET /api/tokens - List tokens (masked)",
        "description": "Everyone sees their own tokens; `api-tokens:read` sees every token. A token\nlimited to other permissions sees none: it must not reach its owner's others.",
        "operationId": "tokens.list",
        "responses": {
          "200": {
            "description": "List of tokens (masked)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuthTokenResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "A token limited to other permissions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Tokens"
        ],
        "summary": "POST /api/tokens - Create a new token (from a signed-in session only)",
        "description": "A token cannot create tokens: a limited or expiring one could otherwise\nmint itself a way out of its limits.",
        "operationId": "tokens.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAuthToken"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Token created (full token shown once)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthTokenCreatedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Called with a token, missing api-tokens:create, or a permission the caller lacks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/tokens/{id}": {
      "get": {
        "tags": [
          "Tokens"
        ],
        "summary": "GET /api/tokens/{id} - Token details, masked",
        "description": "Tokens are stored hashed, so the full value is only ever shown on\ncreation. Everyone may view their own; `api-tokens:read` views any.",
        "operationId": "tokens.get",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Token ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Token details (masked)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthTokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Tokens"
        ],
        "summary": "DELETE /api/tokens/{id} - Revoke a token",
        "description": "Everyone may revoke their own; `api-tokens:delete` revokes any.",
        "operationId": "tokens.delete",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Token ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Token revoked"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/api/users/{id}/assignments": {
      "get": {
        "tags": [
          "Access"
        ],
        "summary": "Lists the roles a user holds, on the instance and on each project.",
        "operationId": "users.assignments",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "User ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "What the user holds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserAccess"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing users:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Access"
        ],
        "summary": "Replaces every role and personal permission a user holds.",
        "description": "The caller must hold every role being given or taken away, on the scope\nit applies to.",
        "operationId": "users.setAssignments",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "User ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetAccess"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "What the user holds now",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserAccess"
                }
              }
            }
          },
          "400": {
            "description": "Unknown role, or personal permissions with no project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing users:update, own assignments, or a role beyond the caller's",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No such user or project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/auth/accept-invitation": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "POST /auth/accept-invitation\nAccept a pending invitation: creates the user (with the invite's email + role) and logs in.",
        "operationId": "auth.acceptInvitation",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptInvitation"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Invitation accepted and user created; signed in unless password login is disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcceptInvitationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or expired invitation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/auth/invitation/{token}": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "GET /auth/invitation/{token}\nReturns the invitation's details if it is still acceptable (for the accept page).",
        "operationId": "auth.getInvitation",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "description": "Invitation token",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation info",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationInfoResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invitation expired or used",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Invitation not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/auth/login": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "POST /auth/login\nAuthenticate user and create session",
        "operationId": "auth.login",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Logged in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Password login is disabled; use SSO",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/auth/logout": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "POST /auth/logout\nClear session",
        "operationId": "auth.logout",
        "responses": {
          "204": {
            "description": "Logged out"
          }
        },
        "security": [
          {
            "session_cookie": []
          }
        ]
      }
    },
    "/auth/me": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "GET /auth/me\nGet current authenticated user",
        "operationId": "auth.getCurrentUser",
        "responses": {
          "200": {
            "description": "Current user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "session_cookie": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Auth"
        ],
        "summary": "PATCH /auth/me\nUpdate the current user's presentation preferences",
        "operationId": "auth.updateCurrentUser",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePreferencesRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Updated user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed language tag or timezone",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "session_cookie": []
          }
        ]
      }
    },
    "/auth/me/password": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "POST /auth/me/password\nChange the current user's password",
        "operationId": "auth.changePassword",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Password changed"
          },
          "400": {
            "description": "Wrong current password or empty new password",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "session_cookie": []
          }
        ]
      }
    },
    "/auth/register": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "POST /auth/register\nRegistration is invite-only — always rejected. Use `/auth/accept-invitation`.",
        "operationId": "auth.register",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUserRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "403": {
            "description": "Registration is invite-only",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/auth/sso/callback": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "GET /auth/sso/callback\nValidate the provider response, resolve or provision the local account, and\nestablish the normal Rustrak session.",
        "operationId": "auth.ssoCallback",
        "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"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SSO login completed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "302": {
            "description": "Browser redirect to the dashboard, the login page, or the account-link page"
          },
          "401": {
            "description": "Invalid or expired callback",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Identity is not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "SSO is not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "An existing account must confirm the link with its password",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/auth/sso/config": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "GET /auth/sso/config\nPublic, non-sensitive information used to render the login page.",
        "operationId": "auth.ssoConfig",
        "responses": {
          "200": {
            "description": "Public SSO configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SsoConfigResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/auth/sso/link": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "GET /auth/sso/link\nThe account an SSO login matched, shown while its owner confirms.",
        "operationId": "auth.ssoLink",
        "responses": {
          "200": {
            "description": "The account waiting for its password",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SsoLinkResponse"
                }
              }
            }
          },
          "404": {
            "description": "No link is pending",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      },
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "POST /auth/sso/link\nLink the pending SSO identity to its account once the account's password\nis given, and sign in. A wrong password keeps the link pending for a retry.",
        "operationId": "auth.confirmSsoLink",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmSsoLinkRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Identity linked and signed in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "401": {
            "description": "Wrong password",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No link is pending",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The identity belongs to another account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/auth/sso/start": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "POST /auth/sso/start\nCreate a one-time OIDC authorization request and retain its protections in\nthe encrypted session cookie.",
        "operationId": "auth.ssoStart",
        "responses": {
          "200": {
            "description": "OIDC authorization URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SsoStartResponse"
                }
              }
            }
          },
          "404": {
            "description": "SSO is disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/health": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Liveness check - is the process running?\nReturns 200 if the server is alive.",
        "operationId": "health.liveness",
        "responses": {
          "200": {
            "description": "Server is alive",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LivenessResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health/ready": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Readiness check - is the service ready to handle requests?\nReturns 200 if all dependencies are available, 503 otherwise.",
        "operationId": "health.readiness",
        "responses": {
          "200": {
            "description": "Service is ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health/version": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Version check - returns the server version compiled from Cargo.toml.",
        "description": "Requires a session cookie or a Bearer token, unlike its neighbours in this\nscope. `/health` and `/health/ready` answer \"is this process up\", which a\nprobe has to be able to ask without credentials; this one answers \"which\nbuild is this\", which is the first thing worth knowing about a host you\nintend to attack.",
        "operationId": "health.version",
        "responses": {
          "200": {
            "description": "Server version info",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          },
          {
            "session_cookie": []
          }
        ]
      }
    },
    "/{org_slug}/{project_slug}/issues/{issue_id}": {
      "get": {
        "tags": [
          "Sentry API"
        ],
        "summary": "GET /{org_slug}/{project_slug}/issues/{issue_id}/",
        "description": "The issue page GitLab's \"View in Sentry\" opens: Sentry redirects this\nlegacy path to the issue (`static/app/router/routes.tsx`), Rustrak to its\ndashboard. A visitor who is not signed in goes to the login page instead,\nso a stranger learns nothing about which issues exist.",
        "operationId": "sentry.openIssue",
        "parameters": [
          {
            "name": "org_slug",
            "in": "path",
            "description": "Organization slug (synthetic — accepted and ignored)",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_slug",
            "in": "path",
            "description": "Project slug (ignored: the id names the issue)",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "issue_id",
            "in": "path",
            "description": "Issue id (`numeric_id`), digits only",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Browser redirect to the issue in the dashboard, or to the login page"
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "session_cookie": []
          },
          {
            "bearer_auth": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AcceptInvitation": {
        "type": "object",
        "required": [
          "token",
          "password"
        ],
        "properties": {
          "password": {
            "type": "string"
          },
          "token": {
            "type": "string"
          }
        }
      },
      "AcceptInvitationResponse": {
        "type": "object",
        "required": [
          "user",
          "signed_in"
        ],
        "properties": {
          "signed_in": {
            "type": "boolean",
            "description": "Whether the response opened a session. False when password login is\ndisabled: the account exists, and its owner signs in through SSO."
          },
          "user": {
            "$ref": "#/components/schemas/UserResponse"
          }
        }
      },
      "Action": {
        "type": "string",
        "description": "Something a grant can allow.",
        "enum": [
          "read",
          "create",
          "update",
          "delete"
        ]
      },
      "ActivityEntry": {
        "type": "object",
        "description": "An entry in an issue's activity log. Comments are stored as activity rows of\ntype `note` with `{\"text\": ...}` in `data` (Sentry models notes as activity).",
        "required": [
          "id",
          "issue_id",
          "user_id",
          "type",
          "data",
          "created_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "issue_id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string"
          },
          "user_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "AgentConversation": {
        "type": "object",
        "description": "A conversation in full: its AI spans across every turn, oldest first,\neach with what went in and came out, for a transcript.",
        "required": [
          "conversation_id",
          "spans"
        ],
        "properties": {
          "conversation_id": {
            "type": "string"
          },
          "spans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationSpan"
            }
          }
        }
      },
      "AgentDurationPoint": {
        "type": "object",
        "description": "avg/p95 duration for one time bucket.",
        "required": [
          "bucket",
          "avg_ms",
          "p95_ms"
        ],
        "properties": {
          "avg_ms": {
            "type": "number",
            "format": "double"
          },
          "bucket": {
            "type": "string",
            "format": "date-time"
          },
          "p95_ms": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "AgentModelRow": {
        "type": "object",
        "description": "One row of the Models table: per response model, the volume, the failures,\nthe latency and the full token split.\n\nCached input and reasoning output are SUBSETS of input/output, not\nadditions — a reader comparing them must not add all four together.",
        "required": [
          "model",
          "requests",
          "errors",
          "avg_ms",
          "p95_ms",
          "input_tokens",
          "cached_input_tokens",
          "output_tokens",
          "reasoning_output_tokens",
          "total_tokens"
        ],
        "properties": {
          "avg_ms": {
            "type": "number",
            "format": "double"
          },
          "cached_input_tokens": {
            "type": "number",
            "format": "double"
          },
          "errors": {
            "type": "integer",
            "format": "int64"
          },
          "input_tokens": {
            "type": "number",
            "format": "double"
          },
          "model": {
            "type": "string"
          },
          "output_tokens": {
            "type": "number",
            "format": "double"
          },
          "p95_ms": {
            "type": "number",
            "format": "double"
          },
          "reasoning_output_tokens": {
            "type": "number",
            "format": "double"
          },
          "requests": {
            "type": "integer",
            "format": "int64"
          },
          "total_tokens": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "AgentSummary": {
        "type": "object",
        "description": "Headline numbers for the agents dashboard, over the selected window.\n\nToken totals exclude `agent`-type spans throughout, for the same reason\nthe Traces table does: an agent span's usage is a client-side rollup of\nits `ai_client` children, so counting both double-counts.",
        "required": [
          "agent_runs",
          "llm_calls",
          "tool_calls",
          "error_count",
          "total_tokens",
          "avg_duration_ms",
          "p95_duration_ms"
        ],
        "properties": {
          "agent_runs": {
            "type": "integer",
            "format": "int64"
          },
          "avg_duration_ms": {
            "type": "number",
            "format": "double",
            "description": "Over `agent` and `ai_client` spans — matching the Duration chart."
          },
          "error_count": {
            "type": "integer",
            "format": "int64",
            "description": "AI spans whose status is set and not `ok`."
          },
          "llm_calls": {
            "type": "integer",
            "format": "int64"
          },
          "p95_duration_ms": {
            "type": "number",
            "format": "double"
          },
          "tool_calls": {
            "type": "integer",
            "format": "int64"
          },
          "total_tokens": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "AgentTimeseriesPoint": {
        "type": "object",
        "description": "One time-bucketed value (count or sum) — mirrors `SessionTimeseriesPoint`.",
        "required": [
          "bucket",
          "value",
          "errors"
        ],
        "properties": {
          "bucket": {
            "type": "string",
            "format": "date-time"
          },
          "errors": {
            "type": "integer",
            "format": "int64",
            "description": "Of the bucket's spans, those whose status is set and not `ok`."
          },
          "value": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "AgentToolRow": {
        "type": "object",
        "description": "One row of the Tools table: per tool, how often it ran and how often it\nfailed. A tool with a high failure rate is the most actionable signal the\nagents page can carry.",
        "required": [
          "tool",
          "calls",
          "errors",
          "avg_ms",
          "p95_ms"
        ],
        "properties": {
          "avg_ms": {
            "type": "number",
            "format": "double"
          },
          "calls": {
            "type": "integer",
            "format": "int64"
          },
          "errors": {
            "type": "integer",
            "format": "int64"
          },
          "p95_ms": {
            "type": "number",
            "format": "double"
          },
          "tool": {
            "type": "string"
          }
        }
      },
      "AgentTraceSummary": {
        "type": "object",
        "description": "One row of the Traces table — per-`trace_id` aggregate across all AI\nspans (standalone and transaction-embedded) sharing that trace.",
        "required": [
          "trace_id",
          "agent_names",
          "duration_ms",
          "total_tokens",
          "tool_call_count",
          "llm_call_count",
          "error_count",
          "started_at"
        ],
        "properties": {
          "agent_names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every distinct agent that ran in this trace, earliest first. A trace\nwith handoffs involves more than one, so this is a list rather than a\nsingle root name — Sentry's own Traces table shows them all."
          },
          "duration_ms": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Duration of the root/longest AI span in this trace, in milliseconds."
          },
          "error_count": {
            "type": "integer",
            "format": "int64",
            "description": "AI spans in this trace whose status is set and not `ok`."
          },
          "llm_call_count": {
            "type": "integer",
            "format": "int64",
            "description": "`ai_client` spans in this trace — how many times a model was actually\ncalled, which is what separates a one-shot answer from an agent loop."
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "tool_call_count": {
            "type": "integer",
            "format": "int64"
          },
          "total_tokens": {
            "type": "number",
            "format": "double"
          },
          "trace_id": {
            "type": "string"
          }
        }
      },
      "AlertHistory": {
        "type": "object",
        "description": "Alert delivery history record (audit log and retry queue)",
        "required": [
          "id",
          "alert_rule_id",
          "integration_id",
          "issue_id",
          "project_id",
          "alert_type",
          "channel_type",
          "channel_name",
          "status",
          "attempt_count",
          "next_retry_at",
          "error_message",
          "http_status_code",
          "idempotency_key",
          "created_at",
          "sent_at"
        ],
        "properties": {
          "alert_rule_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "alert_type": {
            "type": "string"
          },
          "attempt_count": {
            "type": "integer",
            "format": "int32"
          },
          "channel_name": {
            "type": "string"
          },
          "channel_type": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "error_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "http_status_code": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "idempotency_key": {
            "type": "string"
          },
          "integration_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "issue_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "next_retry_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "project_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "$ref": "#/components/schemas/AlertStatus"
          }
        }
      },
      "AlertHistoryDay": {
        "type": "object",
        "description": "One UTC day of deliveries, by outcome: one rule's when the request named\na rule, the whole project's otherwise.",
        "required": [
          "day",
          "sent",
          "failed",
          "skipped"
        ],
        "properties": {
          "day": {
            "type": "string",
            "format": "date-time",
            "description": "Midnight UTC."
          },
          "failed": {
            "type": "integer",
            "format": "int64"
          },
          "sent": {
            "type": "integer",
            "format": "int64"
          },
          "skipped": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "AlertIntegration": {
        "type": "object",
        "description": "Global alert integration record — stores credentials only, no routing.",
        "required": [
          "id",
          "name",
          "provider_type",
          "credentials",
          "is_enabled",
          "failure_count",
          "last_failure_at",
          "last_failure_message",
          "last_success_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "credentials": {
            "type": "object"
          },
          "failure_count": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "is_enabled": {
            "type": "boolean"
          },
          "last_failure_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_failure_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_success_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "provider_type": {
            "$ref": "#/components/schemas/ProviderType"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AlertRuleChannelInput": {
        "type": "object",
        "description": "DTO for a channel with routing override in rule create/update",
        "required": [
          "integration_id"
        ],
        "properties": {
          "integration_id": {
            "type": "integer",
            "format": "int32"
          },
          "routing_override": {
            "type": "object"
          }
        }
      },
      "AlertRuleResponse": {
        "type": "object",
        "description": "Response for alert rule including linked integration info",
        "required": [
          "id",
          "project_id",
          "name",
          "alert_type",
          "is_enabled",
          "conditions",
          "cooldown_minutes",
          "last_triggered_at",
          "channels",
          "integration_ids",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "alert_type": {
            "$ref": "#/components/schemas/AlertType"
          },
          "channels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertRuleChannelInput"
            },
            "description": "All linked integrations including routing_override per channel."
          },
          "conditions": {
            "type": "object"
          },
          "cooldown_minutes": {
            "type": "integer",
            "format": "int32"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "integration_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "Flat list of integration IDs (backward compat, derived from channels)."
          },
          "is_enabled": {
            "type": "boolean"
          },
          "last_triggered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AlertStatus": {
        "type": "string",
        "description": "Status of an alert delivery attempt",
        "enum": [
          "pending",
          "sent",
          "failed",
          "skipped"
        ]
      },
      "AlertType": {
        "type": "string",
        "description": "Type of alert trigger",
        "enum": [
          "new_issue",
          "regression",
          "unmute",
          "new_feedback"
        ]
      },
      "AssembleBody": {
        "type": "object",
        "required": [
          "checksum",
          "chunks",
          "projects"
        ],
        "properties": {
          "checksum": {
            "type": "string"
          },
          "chunks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "projects": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "AssembleResponse": {
        "type": "object",
        "required": [
          "state",
          "missingChunks"
        ],
        "properties": {
          "detail": {
            "type": [
              "string",
              "null"
            ]
          },
          "missingChunks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "state": {
            "type": "string"
          }
        }
      },
      "AssignmentInput": {
        "type": "object",
        "required": [
          "role_id"
        ],
        "properties": {
          "project_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "`null` reaches every project."
          },
          "role_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AttachmentBytes": {
        "description": "The raw bytes of an attachment. Untyped in the spec: the generated\nclient validates bodies with zod, which has no type for a binary one."
      },
      "AttachmentInfo": {
        "type": "object",
        "description": "An attachment, without its bytes.",
        "required": [
          "id",
          "event_id",
          "filename",
          "content_type",
          "size",
          "created_at"
        ],
        "properties": {
          "content_type": {
            "type": "string",
            "description": "As the SDK declared it; the download trusts only the bytes."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "event_id": {
            "type": "string",
            "format": "uuid",
            "description": "The event it was sent with (the stored row's id)."
          },
          "filename": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "size": {
            "type": "integer",
            "format": "int32",
            "description": "Size in bytes."
          }
        }
      },
      "AuthResponse": {
        "type": "object",
        "required": [
          "user"
        ],
        "properties": {
          "user": {
            "$ref": "#/components/schemas/UserResponse"
          }
        }
      },
      "AuthTokenCreatedResponse": {
        "type": "object",
        "description": "Response that includes the full token (only on creation)",
        "required": [
          "id",
          "token",
          "description",
          "created_at",
          "permissions",
          "project_ids",
          "expires_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "permissions": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/Permission"
            },
            "description": "`null`: everything its owner may do."
          },
          "project_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "`null`: every project its owner reaches."
          },
          "token": {
            "type": "string"
          }
        }
      },
      "AuthTokenResponse": {
        "type": "object",
        "description": "Response for listing (token is masked)",
        "required": [
          "id",
          "token_prefix",
          "description",
          "user_id",
          "created_at",
          "last_used_at",
          "permissions",
          "project_ids",
          "expires_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "permissions": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/Permission"
            },
            "description": "`null`: everything its owner may do."
          },
          "project_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "`null`: every project its owner reaches."
          },
          "token_prefix": {
            "type": "string"
          },
          "user_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "AuthorizationDecision": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AuthorizationRequest"
          },
          {
            "type": "object",
            "required": [
              "approve"
            ],
            "properties": {
              "approve": {
                "type": "boolean"
              }
            }
          }
        ],
        "description": "The user's answer to a consent screen."
      },
      "AuthorizationInfo": {
        "type": "object",
        "description": "What the consent page shows about the client asking.",
        "required": [
          "client_id",
          "client_name",
          "redirect_host"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          },
          "redirect_host": {
            "type": "string",
            "description": "Host the user is sent back to, the one fact a lookalike name cannot fake."
          }
        }
      },
      "AuthorizationRedirect": {
        "type": "object",
        "description": "Where the consent page sends the browser next.",
        "required": [
          "redirect_to"
        ],
        "properties": {
          "redirect_to": {
            "type": "string"
          }
        }
      },
      "AuthorizationRequest": {
        "type": "object",
        "description": "An authorization request, as the client put it in the authorize URL.",
        "required": [
          "response_type",
          "client_id",
          "redirect_uri",
          "code_challenge",
          "code_challenge_method"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "code_challenge": {
            "type": "string"
          },
          "code_challenge_method": {
            "type": "string"
          },
          "redirect_uri": {
            "type": "string"
          },
          "resource": {
            "type": [
              "string",
              "null"
            ]
          },
          "response_type": {
            "type": "string"
          },
          "state": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "BookmarkResponse": {
        "type": "object",
        "required": [
          "is_bookmarked"
        ],
        "properties": {
          "is_bookmarked": {
            "type": "boolean"
          }
        }
      },
      "BulkDeleteIssues": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "ids"
            ],
            "properties": {
              "ids": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "maxProperties": 1
          },
          {
            "type": "object",
            "required": [
              "filter"
            ],
            "properties": {
              "filter": {
                "$ref": "#/components/schemas/IssueFilter"
              }
            },
            "maxProperties": 1
          }
        ],
        "description": "Bulk delete request: the listed `ids`, or every issue matching `filter`.\nA body with neither or both matches no variant and is rejected, so an empty\nbody can never mean \"all\"."
      },
      "BulkDeleteResponse": {
        "type": "object",
        "required": [
          "deleted"
        ],
        "properties": {
          "deleted": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "BulkUpdateIssues": {
        "type": "object",
        "description": "Bulk mutate request: apply a status (and/or priority) to many issues.",
        "required": [
          "ids"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "priority": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/IssuePriority"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/IssueStatusUpdate"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "BulkUpdateResponse": {
        "type": "object",
        "required": [
          "updated"
        ],
        "properties": {
          "updated": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "Catalog": {
        "type": "object",
        "required": [
          "resources"
        ],
        "properties": {
          "resources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogResource"
            }
          }
        }
      },
      "CatalogResource": {
        "type": "object",
        "required": [
          "key",
          "module",
          "scope",
          "actions"
        ],
        "properties": {
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Action"
            }
          },
          "key": {
            "type": "string"
          },
          "module": {
            "type": "string"
          },
          "scope": {
            "$ref": "#/components/schemas/Scope"
          }
        }
      },
      "ChangePasswordRequest": {
        "type": "object",
        "required": [
          "current_password",
          "new_password"
        ],
        "properties": {
          "current_password": {
            "type": "string"
          },
          "new_password": {
            "type": "string"
          }
        }
      },
      "CheckInResponse": {
        "type": "object",
        "description": "One check-in, as the dashboard reads it.",
        "required": [
          "id",
          "environment",
          "status",
          "duration_ms",
          "date_added",
          "date_updated",
          "expected_time"
        ],
        "properties": {
          "date_added": {
            "type": "string",
            "format": "date-time"
          },
          "date_updated": {
            "type": "string",
            "format": "date-time"
          },
          "duration_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "environment": {
            "type": "string"
          },
          "expected_time": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/CheckInStatus"
          }
        }
      },
      "CheckInStatus": {
        "type": "string",
        "description": "Status of one check-in. `Missed` and `Timeout` are only ever set by the\nserver.",
        "enum": [
          "ok",
          "error",
          "in_progress",
          "missed",
          "timeout",
          "unknown"
        ]
      },
      "ChunkUploadBody": {
        "type": "object",
        "description": "Multipart chunk upload.\nEach part's **field name** may be the SHA-1 hex digest of that part's binary content\n(sentry-cli v2 protocol, e.g. `da39a3ee5e6b4b0d3255bfef95601890afd80709`) or an arbitrary\nname like `file` (sentry-cli v3.x). Up to 64 parts per request; each part body is raw binary."
      },
      "ChunkUploadOptions": {
        "type": "object",
        "description": "Chunk upload capabilities, in sentry-cli's camelCase.",
        "required": [
          "url",
          "chunkSize",
          "chunksPerRequest",
          "maxRequestSize",
          "hashAlgorithm",
          "accept",
          "concurrency",
          "compression"
        ],
        "properties": {
          "accept": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "chunkSize": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "chunksPerRequest": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "compression": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Required by the `sentry` npm uploader that Sentry SDK v11 bundler\nplugins use; it rejects the response without it. Empty means chunks\nare sent uncompressed, which is what `chunk_upload` reads."
          },
          "concurrency": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "hashAlgorithm": {
            "type": "string"
          },
          "maxRequestSize": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "url": {
            "type": "string"
          }
        }
      },
      "CleanupCounts": {
        "type": "object",
        "description": "Rows affected by a cleanup, used symmetrically for the dry-run preview (\"what\nwould be removed\") and the executed result (\"what was removed\"). `spans` are\ncounted directly even though they cascade from `transactions`, so the UI can\nshow the true row impact. `issues_removed` is the number of issues that would\nbe left with zero events and therefore deleted.",
        "required": [
          "events",
          "transactions",
          "spans",
          "logs",
          "issues_removed",
          "source_maps"
        ],
        "properties": {
          "events": {
            "type": "integer",
            "format": "int64"
          },
          "issues_removed": {
            "type": "integer",
            "format": "int64"
          },
          "logs": {
            "type": "integer",
            "format": "int64"
          },
          "source_maps": {
            "type": "integer",
            "format": "int64",
            "description": "Unused source maps deleted; only a retention cleanup removes them."
          },
          "spans": {
            "type": "integer",
            "format": "int64"
          },
          "transactions": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "CleanupFrequency": {
        "type": "string",
        "description": "How often the cleanup that enforces retention runs.",
        "enum": [
          "daily",
          "weekly"
        ]
      },
      "CleanupKind": {
        "type": "string",
        "description": "What the job is doing: deleting old data, or compacting the SQLite file.",
        "enum": [
          "cleanup",
          "compaction"
        ]
      },
      "CleanupRequest": {
        "type": "object",
        "description": "Request body for a cleanup (preview or execute): remove data older than\n`older_than_days`, optionally scoped to a single project (omit for all).\n\n`older_than_days` must be at least 1 — the service rejects smaller values,\nsince a window of 0 (or negative) would move the cutoff to now/the future and\npurge the entire dataset.",
        "required": [
          "older_than_days"
        ],
        "properties": {
          "include_events": {
            "type": "boolean",
            "description": "Whether to purge error events (and the issues they empty). Defaults to\n`true` so an older client that omits it keeps the \"delete everything\"\nbehaviour."
          },
          "include_logs": {
            "type": "boolean",
            "description": "Whether to purge logs. Defaults to `true`."
          },
          "include_transactions": {
            "type": "boolean",
            "description": "Whether to purge transactions (and their cascaded spans). Defaults to `true`."
          },
          "older_than_days": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "project_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "CleanupState": {
        "type": "string",
        "description": "Where the instance's cleanup job is. There is at most one at a time.",
        "enum": [
          "idle",
          "running",
          "completed",
          "failed"
        ]
      },
      "CleanupStatus": {
        "type": "object",
        "description": "The cleanup job as the API reports it. Kept in memory: a restart forgets\nit, and a run cut short by one is simply run again, since every batch it\ncommitted is already gone.",
        "required": [
          "state",
          "kind",
          "removed",
          "started_at",
          "finished_at",
          "error"
        ],
        "properties": {
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why a `failed` run stopped. Batches committed before it stay deleted."
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "kind": {
            "$ref": "#/components/schemas/CleanupKind"
          },
          "removed": {
            "$ref": "#/components/schemas/CleanupCounts",
            "description": "Rows removed so far while `running`; the total once it has finished."
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "state": {
            "$ref": "#/components/schemas/CleanupState"
          }
        }
      },
      "CodeMapping": {
        "type": "object",
        "description": "Maps a path as it appears in a stack trace to the path in the repository.",
        "required": [
          "stack_root",
          "source_root"
        ],
        "properties": {
          "source_root": {
            "type": "string",
            "description": "Prefix put in its place, e.g. `src/`. Empty for the repository root."
          },
          "stack_root": {
            "type": "string",
            "description": "Prefix stripped from the frame's path, e.g. `/app/` or `webpack:///./`."
          }
        }
      },
      "CommentRequest": {
        "type": "object",
        "description": "Body for creating an issue comment (note).",
        "required": [
          "text"
        ],
        "properties": {
          "text": {
            "type": "string"
          }
        }
      },
      "Compaction": {
        "type": "object",
        "description": "Whether the SQLite file can give the space a cleanup frees back to the\ndisk, and what compacting it once would take.\n\nA database created before Rustrak set `auto_vacuum = INCREMENTAL` keeps\nSQLite's default, `NONE`: its freed pages are reused but the file never\nshrinks. One `VACUUM` rewrites it in incremental mode. Always\n`needed: false` on Postgres, whose autovacuum gives the space back.",
        "required": [
          "needed",
          "file_bytes",
          "live_bytes",
          "reclaimable_bytes",
          "required_disk_bytes",
          "free_disk_bytes"
        ],
        "properties": {
          "file_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "The database file's size."
          },
          "free_disk_bytes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Free disk next to the database, `null` when it cannot be read."
          },
          "live_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "What the data in it takes, the part a compaction keeps."
          },
          "needed": {
            "type": "boolean"
          },
          "reclaimable_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Free pages inside the file, the part a compaction gives back."
          },
          "required_disk_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Free disk a compaction needs: twice the live data, one copy in\nSQLite's temporary file and one in the write-ahead log."
          }
        }
      },
      "ConfirmSsoLinkRequest": {
        "type": "object",
        "required": [
          "password"
        ],
        "properties": {
          "password": {
            "type": "string"
          }
        }
      },
      "ConversationSpan": {
        "type": "object",
        "required": [
          "id",
          "trace_id",
          "span_id",
          "parent_span_id",
          "operation_type",
          "agent_name",
          "model",
          "tool_name",
          "status",
          "start_timestamp",
          "duration_ms",
          "total_tokens",
          "input",
          "output",
          "tool_calls"
        ],
        "properties": {
          "agent_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "input": {
            "type": [
              "string",
              "null"
            ],
            "description": "The prompt or the tool's arguments, verbatim."
          },
          "model": {
            "type": [
              "string",
              "null"
            ],
            "description": "The response model, else the request model."
          },
          "operation_type": {
            "type": "string",
            "description": "`agent`, `ai_client`, `tool` or `handoff`."
          },
          "output": {
            "type": [
              "string",
              "null"
            ],
            "description": "The answer or the tool's result, verbatim."
          },
          "parent_span_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "span_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "start_timestamp": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "tool_calls": {
            "type": [
              "string",
              "null"
            ],
            "description": "The tool calls the model asked for."
          },
          "tool_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "total_tokens": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "trace_id": {
            "type": "string"
          }
        }
      },
      "CreateAlertIntegration": {
        "type": "object",
        "description": "DTO for creating an alert integration",
        "required": [
          "name",
          "provider_type",
          "credentials"
        ],
        "properties": {
          "credentials": {
            "type": "object"
          },
          "is_enabled": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "provider_type": {
            "$ref": "#/components/schemas/ProviderType"
          }
        }
      },
      "CreateAlertRule": {
        "type": "object",
        "description": "DTO for creating an alert rule",
        "required": [
          "name",
          "alert_type"
        ],
        "properties": {
          "alert_type": {
            "$ref": "#/components/schemas/AlertType"
          },
          "channels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertRuleChannelInput"
            }
          },
          "conditions": {
            "type": "object"
          },
          "cooldown_minutes": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "CreateAuthToken": {
        "type": "object",
        "description": "DTO for creating a new token",
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it stops working. Omitted or `null`: never."
          },
          "permissions": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/Permission"
            },
            "description": "What the token may do, within its owner's permissions. Omitted or\n`null`: everything its owner may do."
          },
          "project_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "The projects it may reach. Omitted or `null`: every project its owner reaches."
          }
        }
      },
      "CreateGitHubIssue": {
        "type": "object",
        "properties": {
          "assignee": {
            "type": [
              "string",
              "null"
            ],
            "description": "A GitHub login. Defaults to the Rustrak assignee's; `\"\"` sends none."
          },
          "body": {
            "type": [
              "string",
              "null"
            ],
            "description": "Defaults to a link back, the latest event's exceptions (else its\nmessage, else the issue's `type: value`) and the templates' body\nfooter; `\"\"` sends an empty one."
          },
          "labels": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Defaults to the templates' labels; `[]` sends none."
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Defaults to the Rustrak issue's title."
          }
        }
      },
      "CreateInvitation": {
        "type": "object",
        "required": [
          "email",
          "role"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "project_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Where `role_id` applies; omitted or `null` is the whole instance."
          },
          "role": {
            "$ref": "#/components/schemas/UserRole",
            "description": "Global role the invited user will receive (`admin` | `member`)."
          },
          "role_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "A role the new user holds once they accept, within the inviter's own\npermissions."
          },
          "send_email": {
            "type": "boolean",
            "description": "Also email the invite link to the recipient (Sentry's `sendInvite`).\nNeeds an enabled email integration or `SMTP_HOST`, and `DASHBOARD_URL`\nor `PUBLIC_URL`. The response\ncarries `token` for manual sharing either way."
          }
        }
      },
      "CreateMonitor": {
        "type": "object",
        "description": "Body of `POST /api/projects/{project_id}/monitors`.",
        "required": [
          "name",
          "config"
        ],
        "properties": {
          "config": {
            "$ref": "#/components/schemas/MonitorConfigInput"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ],
            "description": "Derived from `name` when left out. This is the slug SDKs check in with."
          }
        }
      },
      "CreateProject": {
        "type": "object",
        "description": "DTO for creating a new project",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "platform": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform identifier for the project, such as `python-django` or\n`javascript-nextjs`. Rejected with a 400 if it is not one of the\nsupported values.\n\nOptional. Omitting it is not the same as having no platform forever:\nthe project is then auto-assigned a platform from the first event it\ningests, drawn from the narrower set of platforms an event may declare."
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CreateRelease": {
        "type": "object",
        "description": "DTO for `POST .../releases/`.",
        "required": [
          "version"
        ],
        "properties": {
          "ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "version": {
            "type": "string"
          }
        }
      },
      "CreateUserRequest": {
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        }
      },
      "DebugFileResponse": {
        "type": "object",
        "description": "A debug information file as Sentry's `DebugFileSerializer` describes it.",
        "required": [
          "id",
          "uuid",
          "debugId",
          "codeId",
          "cpuName",
          "objectName",
          "symbolType",
          "headers",
          "size",
          "sha1",
          "dateCreated",
          "data"
        ],
        "properties": {
          "codeId": {
            "type": [
              "string",
              "null"
            ]
          },
          "cpuName": {
            "type": "string"
          },
          "data": {},
          "dateCreated": {
            "type": "string"
          },
          "debugId": {
            "type": "string"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "id": {
            "type": "string"
          },
          "objectName": {
            "type": "string"
          },
          "sha1": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "symbolType": {
            "type": "string"
          },
          "uuid": {
            "type": "string"
          }
        }
      },
      "DifAssembleFile": {
        "type": "object",
        "description": "One file of a debug information file assemble request.",
        "required": [
          "name",
          "chunks"
        ],
        "properties": {
          "chunks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "debug_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          }
        }
      },
      "DifUploadBody": {
        "type": "object",
        "description": "Multipart legacy debug file upload: one `file` part holding a zip."
      },
      "EmailStatusResponse": {
        "type": "object",
        "description": "GET /api/invitations/email-status answer.",
        "required": [
          "available"
        ],
        "properties": {
          "available": {
            "type": "boolean",
            "description": "Whether invitation emails can be sent: `SMTP_HOST` is set, and so is\n`DASHBOARD_URL` or `PUBLIC_URL` for the link."
          }
        }
      },
      "ErrorDetail": {
        "type": "object",
        "required": [
          "type",
          "message"
        ],
        "properties": {
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldError"
            },
            "description": "Machine-readable annotations naming the inputs that were rejected.\n\nOmitted from the JSON entirely when empty, so every consumer written\nbefore this existed keeps seeing exactly the body it saw before."
          },
          "incident_id": {
            "type": "string",
            "description": "Correlates this response with the `log::error!` line that carries the\ndetail [`INTERNAL_ERROR_MESSAGE`] replaced.\n\nPresent on every 5xx and on nothing else: a 4xx says what went wrong in\n`message`, logs nothing, and so has no line for an id to point at.\n\n`nullable = false`: `skip_serializing_if` means the key is *absent* on\na 4xx, never `null`."
          },
          "message": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "JSON error response structure",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        }
      },
      "EventDetailResponse": {
        "type": "object",
        "description": "Response for API (full detail)",
        "required": [
          "id",
          "event_id",
          "issue_id",
          "title",
          "timestamp",
          "ingested_at",
          "level",
          "platform",
          "release",
          "environment",
          "server_name",
          "sdk_name",
          "sdk_version",
          "event_type",
          "data"
        ],
        "properties": {
          "data": {
            "type": "object"
          },
          "environment": {
            "type": "string"
          },
          "event_id": {
            "type": "string",
            "description": "Sentry event ID: 32 hex digits, not necessarily an RFC 4122 UUID."
          },
          "event_type": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ingested_at": {
            "type": "string",
            "format": "date-time"
          },
          "issue_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "level": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "release": {
            "type": "string"
          },
          "sdk_name": {
            "type": "string"
          },
          "sdk_version": {
            "type": "string"
          },
          "server_name": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "title": {
            "type": "string"
          }
        }
      },
      "EventResponse": {
        "type": "object",
        "description": "Response for API (list view)",
        "required": [
          "id",
          "event_id",
          "issue_id",
          "title",
          "timestamp",
          "level",
          "platform",
          "release",
          "environment",
          "event_type"
        ],
        "properties": {
          "environment": {
            "type": "string"
          },
          "event_id": {
            "type": "string",
            "description": "Sentry event ID: 32 hex digits, not necessarily an RFC 4122 UUID."
          },
          "event_type": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "issue_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "level": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "release": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "title": {
            "type": "string"
          }
        }
      },
      "EventTimeseriesPoint": {
        "type": "object",
        "description": "One time-bucketed point in a project's error-event volume, split by severity.\n\n`total` always equals `fatal + error + warning + info`: `info` absorbs\n`debug` and any level the SDK sent that we do not model, so the stacked\nsegments of a chart always sum to the bar height and no events silently\nvanish from the series.",
        "required": [
          "bucket",
          "total",
          "fatal",
          "error",
          "warning",
          "info"
        ],
        "properties": {
          "bucket": {
            "type": "string",
            "format": "date-time"
          },
          "error": {
            "type": "integer",
            "format": "int64"
          },
          "fatal": {
            "type": "integer",
            "format": "int64"
          },
          "info": {
            "type": "integer",
            "format": "int64"
          },
          "total": {
            "type": "integer",
            "format": "int64"
          },
          "warning": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "FeedbackResponse": {
        "type": "object",
        "description": "A user feedback: its issue's state and what the user submitted\n(`contexts.feedback`, develop.sentry.dev/sdk/telemetry/feedbacks/).",
        "required": [
          "id",
          "status",
          "message",
          "name",
          "contact_email",
          "url",
          "associated_event_id",
          "created_at",
          "attachments"
        ],
        "properties": {
          "associated_event_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The SDK id of the error event it is about."
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttachmentInfo"
            },
            "description": "Files sent with it, such as a screenshot."
          },
          "contact_email": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The feedback's issue."
          },
          "message": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/IssueStatus"
          },
          "url": {
            "type": "string",
            "description": "The page it was sent from."
          }
        }
      },
      "FieldError": {
        "type": "object",
        "description": "One rejected input, named as data rather than buried in the prose of\n[`ErrorDetail::message`].\n\n`field` is a **dot path into the request body** (`slug`,\n`credentials.webhook_url`), not a JSON Pointer and not a UI label: a\nconsumer feeds it straight to a form library's `setError`.\n\nThe rejected *value* is deliberately never echoed back. One careless\napplication to a password input would put a credential in the log store.\n\nThe three fields are private on purpose. [`Self::new`] and [`Self::custom`]\nare the only ways to build one, which is what makes \"`message` is populated\nonly alongside [`FieldErrorCode::Custom`]\" an invariant the compiler holds\nrather than a convention a struct literal could quietly break.",
        "required": [
          "field",
          "code"
        ],
        "properties": {
          "code": {
            "$ref": "#/components/schemas/FieldErrorCode"
          },
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "description": "Only for what [`FieldErrorCode`] cannot express, and then only\nalongside [`FieldErrorCode::Custom`]. Consumers pick their copy from\n`(field, code)` so it can be translated, and never parse this.\n\n`nullable = false`: `skip_serializing_if` means the key is *absent*,\nnever `null`, so a generated client must not model a null it can never\nreceive."
          }
        }
      },
      "FieldErrorCode": {
        "type": "string",
        "description": "The closed vocabulary a [`FieldError`] may use.\n\nDeliberately small and resource-agnostic: a large or per-endpoint\nvocabulary becomes a public API that cannot be versioned. Adding a variant\nis a wire change and requires the matching addition to the TypeScript union\nin `packages/client/src/errors.ts`, which\n`packages/client/tests/unit/app-error-contract.test.ts` enforces by parsing\nthis enum out of this file.",
        "enum": [
          "required",
          "invalid",
          "already_exists",
          "too_short",
          "too_long",
          "custom"
        ]
      },
      "GenAiBreakdownRow": {
        "type": "object",
        "description": "One row of a \"top N by X\" breakdown (model or tool name).",
        "required": [
          "label",
          "value"
        ],
        "properties": {
          "label": {
            "type": "string"
          },
          "value": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "GitHubAppInfo": {
        "type": "object",
        "required": [
          "app_id",
          "slug",
          "html_url",
          "owner_login",
          "install_url",
          "last_webhook_at",
          "created_at"
        ],
        "properties": {
          "app_id": {
            "type": "integer",
            "format": "int64"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "html_url": {
            "type": "string"
          },
          "install_url": {
            "type": "string",
            "description": "Where people install the app on an account or organization."
          },
          "last_webhook_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "owner_login": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "GitHubInstallation": {
        "type": "object",
        "required": [
          "id",
          "account_login",
          "account_type",
          "suspended",
          "created_at"
        ],
        "properties": {
          "account_login": {
            "type": "string"
          },
          "account_type": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "suspended": {
            "type": "boolean"
          }
        }
      },
      "GitHubIssueDraft": {
        "type": "object",
        "description": "`GET .../github/draft`: what creating a GitHub issue sends by default, for\nthe person to edit first.",
        "required": [
          "title",
          "body",
          "labels",
          "assignee",
          "assignees"
        ],
        "properties": {
          "assignee": {
            "type": [
              "string",
              "null"
            ],
            "description": "The Rustrak assignee's GitHub login, if they set one."
          },
          "assignees": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The logins GitHub lets the repository's issues be assigned to."
          },
          "body": {
            "type": "string"
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "title": {
            "type": "string"
          }
        }
      },
      "GitHubLogin": {
        "type": "object",
        "required": [
          "login"
        ],
        "properties": {
          "login": {
            "type": [
              "string",
              "null"
            ],
            "description": "The person's GitHub username; `null` clears it."
          }
        }
      },
      "GitHubRepository": {
        "type": "object",
        "description": "A repository an installation can reach.",
        "required": [
          "installation_id",
          "full_name",
          "default_branch",
          "private",
          "html_url"
        ],
        "properties": {
          "default_branch": {
            "type": "string"
          },
          "full_name": {
            "type": "string"
          },
          "html_url": {
            "type": "string"
          },
          "installation_id": {
            "type": "integer",
            "format": "int64"
          },
          "private": {
            "type": "boolean"
          }
        }
      },
      "GitHubStatus": {
        "type": "object",
        "description": "`GET /api/github`: everything the integrations page needs in one answer.",
        "required": [
          "app",
          "installations",
          "webhook_url",
          "issue_template"
        ],
        "properties": {
          "app": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/GitHubAppInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "installations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GitHubInstallation"
            }
          },
          "issue_template": {
            "$ref": "#/components/schemas/IssueTemplate",
            "description": "What every GitHub issue starts with. Until an admin sets it: no\nlabels, an empty title prefix and an empty body footer."
          },
          "webhook_url": {
            "type": "string",
            "description": "The address GitHub delivers webhooks to."
          }
        }
      },
      "Grouping": {
        "type": "object",
        "description": "Grouping model - maps a grouping key to an issue",
        "required": [
          "id",
          "project_id",
          "issue_id",
          "grouping_key",
          "grouping_key_hash",
          "created_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "grouping_key": {
            "type": "string"
          },
          "grouping_key_hash": {
            "type": "string"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "issue_id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "IntervalUnit": {
        "type": "string",
        "enum": [
          "minute",
          "hour",
          "day",
          "week",
          "month",
          "year"
        ]
      },
      "InvitationInfoResponse": {
        "type": "object",
        "description": "Public-facing invitation info for the accept page.",
        "required": [
          "email",
          "role",
          "status",
          "expires_at"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "role": {
            "$ref": "#/components/schemas/UserRole"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "InvitationResponse": {
        "type": "object",
        "description": "Public-facing invitation (no internal columns beyond what the UI needs).",
        "required": [
          "id",
          "token",
          "email",
          "role",
          "status",
          "expires_at",
          "created_at",
          "email_sent_at",
          "role_id",
          "project_id"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "email": {
            "type": "string"
          },
          "email_sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the invitation email was last sent; null when none was."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "description": "What resending and revoking address it by."
          },
          "project_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "role": {
            "$ref": "#/components/schemas/UserRole"
          },
          "role_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "status": {
            "type": "string"
          },
          "token": {
            "type": [
              "string",
              "null"
            ],
            "description": "Claims the account, so it is `null` for a reader who could not have\ncreated this invitation."
          }
        }
      },
      "IssueAggregates": {
        "type": "object",
        "description": "Per-issue aggregates computed from recent events (capped scan).",
        "required": [
          "user_count",
          "tags"
        ],
        "properties": {
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TagSummary"
            }
          },
          "user_count": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "IssueCategory": {
        "type": "string",
        "description": "Which kind of issue a list shows. Feedback is kept out of the default\nlist, as Sentry's `FeedbackGroup` is (`in_default_search=False`).",
        "enum": [
          "error",
          "feedback"
        ]
      },
      "IssueFilter": {
        "type": "string",
        "description": "Filter for issues listing",
        "enum": [
          "open",
          "resolved",
          "muted",
          "all"
        ]
      },
      "IssueGitHub": {
        "type": "object",
        "description": "`GET .../issues/{id}/github`: the issue's \"Code\" block in one answer.",
        "required": [
          "links",
          "suspect_commits",
          "owners"
        ],
        "properties": {
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IssueLink"
            }
          },
          "owners": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Owners of the culprit file according to CODEOWNERS."
          },
          "suspect_commits": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RepoCommit"
            },
            "description": "Commits that touched the issue's culprit file shortly before it first\nappeared, newest first."
          }
        }
      },
      "IssueLink": {
        "type": "object",
        "required": [
          "id",
          "issue_id",
          "repo_full_name",
          "number",
          "title",
          "url",
          "state",
          "created_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "issue_id": {
            "type": "string",
            "format": "uuid"
          },
          "number": {
            "type": "integer",
            "format": "int64"
          },
          "repo_full_name": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "description": "`open` or `closed`, as of the last webhook or sync."
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        }
      },
      "IssuePriority": {
        "type": "string",
        "description": "Triage priority of an issue.",
        "enum": [
          "low",
          "medium",
          "high"
        ]
      },
      "IssueResponse": {
        "type": "object",
        "description": "Response for API",
        "required": [
          "id",
          "project_id",
          "short_id",
          "title",
          "value",
          "culprit",
          "logger",
          "first_seen",
          "last_seen",
          "event_count",
          "level",
          "platform",
          "status",
          "substatus",
          "priority",
          "assigned_to",
          "assignee_type",
          "issue_type",
          "issue_category",
          "first_release",
          "last_release",
          "status_details",
          "is_resolved",
          "is_muted"
        ],
        "properties": {
          "assigned_to": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "assignee_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "culprit": {
            "type": "string"
          },
          "event_count": {
            "type": "integer",
            "format": "int32"
          },
          "first_release": {
            "type": "string"
          },
          "first_seen": {
            "type": "string",
            "format": "date-time"
          },
          "has_seen": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "is_bookmarked": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_muted": {
            "type": "boolean",
            "description": "Deprecated: derived from `status`. See `is_resolved`."
          },
          "is_resolved": {
            "type": "boolean",
            "description": "Deprecated: derived from `status`. Kept for the legacy client/UI until\nthey migrate to `status`. Remove in the client/frontend phases of #165."
          },
          "is_subscribed": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "issue_category": {
            "type": "string"
          },
          "issue_type": {
            "type": "string"
          },
          "last_release": {
            "type": "string"
          },
          "last_seen": {
            "type": "string",
            "format": "date-time"
          },
          "level": {
            "type": [
              "string",
              "null"
            ]
          },
          "logger": {
            "type": "string"
          },
          "platform": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/IssuePriority"
              },
              {
                "type": "null"
              }
            ]
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          },
          "short_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/IssueStatus"
          },
          "status_details": {
            "type": "object"
          },
          "substatus": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": "string"
          },
          "trend": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int64"
            },
            "description": "24 hourly buckets, oldest to newest. Only populated by the issue list\nendpoint."
          },
          "user_count": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Only populated by the issue list endpoint (bulk-computed per page)."
          },
          "user_report_count": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Only populated by the single-issue GET endpoint."
          },
          "value": {
            "type": "string"
          }
        }
      },
      "IssueSort": {
        "type": "string",
        "description": "Sort mode for issues listing",
        "enum": [
          "digest_order",
          "last_seen",
          "event_count",
          "first_seen",
          "priority"
        ]
      },
      "IssueStatsResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "integer",
                "format": "int64"
              }
            },
            "description": "Each point is `[bucketStartUnix, count]`."
          }
        }
      },
      "IssueStatsWindow": {
        "type": "string",
        "description": "How far back issue stats reach.",
        "enum": [
          "24h",
          "30d"
        ]
      },
      "IssueStatus": {
        "type": "string",
        "description": "Lifecycle status of an issue (Sentry-compatible).",
        "enum": [
          "unresolved",
          "resolved",
          "ignored"
        ]
      },
      "IssueStatusUpdate": {
        "type": "string",
        "description": "The status an update may set: an [`IssueStatus`], or `resolvedInNextRelease`\nto resolve until the next release ships.",
        "enum": [
          "unresolved",
          "resolved",
          "ignored",
          "resolvedInNextRelease"
        ]
      },
      "IssueTagValue": {
        "type": "object",
        "description": "A single tag value's usage within an issue — the shape `GET\n/issues/{id}/tags/{key}` returns per entry, matching Sentry's\n`TagValueSerializerResponse` (src/sentry/tagstore/types.py:166-173):\na bare list of these, not `{key, values}`.",
        "required": [
          "key",
          "name",
          "value",
          "count",
          "first_seen",
          "last_seen"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "format": "int64"
          },
          "first_seen": {
            "type": "string",
            "format": "date-time"
          },
          "key": {
            "type": "string"
          },
          "last_seen": {
            "type": "string",
            "format": "date-time"
          },
          "name": {
            "type": "string",
            "description": "Display name for the tag key. Real Sentry has a reserved-key display\nname table; Rustrak doesn't, so this currently just mirrors `key`."
          },
          "value": {
            "type": "string"
          }
        }
      },
      "IssueTemplate": {
        "type": "object",
        "description": "What a GitHub issue Rustrak opens starts with. A project's template goes\non top of the instance's: its labels add to them, and its title prefix\nand body footer replace theirs unless empty.",
        "properties": {
          "body_footer": {
            "type": "string",
            "description": "Markdown appended to the body, e.g. `cc @acme/oncall`. At most 10000\ncharacters."
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "title_prefix": {
            "type": "string",
            "description": "Put before the Rustrak issue's title, e.g. `[Rustrak] `."
          }
        }
      },
      "IssueUpdate": {
        "type": "object",
        "description": "Body of an issue update: the fields of `GroupValidator`\n(`api/helpers/group_index/validators/group.py`) Rustrak acts on.",
        "properties": {
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "`resolved`, `unresolved`, `ignored`, `resolvedInNextRelease` or `muted`."
          },
          "substatus": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "KindAge": {
        "type": "object",
        "description": "How long ago a kind of data arrived: rows per age bucket, and the oldest.",
        "required": [
          "counts",
          "oldest"
        ],
        "properties": {
          "counts": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            },
            "description": "One count per bucket, `AGE_BUCKET_DAYS.len() + 1` of them."
          },
          "oldest": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "LinkGitHubIssue": {
        "type": "object",
        "required": [
          "reference"
        ],
        "properties": {
          "reference": {
            "type": "string",
            "description": "A GitHub issue or pull request URL, or `#123` for the project's\nrepository."
          }
        }
      },
      "LivenessResponse": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string"
          }
        }
      },
      "LogResponse": {
        "type": "object",
        "description": "Response model for a single stored log in the list view.",
        "required": [
          "id",
          "trace_id",
          "span_id",
          "level",
          "severity_number",
          "body",
          "attributes",
          "timestamp",
          "ingested_at"
        ],
        "properties": {
          "attributes": {
            "type": "object",
            "description": "Typed attribute map, as received."
          },
          "body": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ingested_at": {
            "type": "string",
            "format": "date-time"
          },
          "level": {
            "type": "string"
          },
          "severity_number": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "OTel severity number (1=trace … 21=fatal). None for unknown levels."
          },
          "span_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "trace_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "LogVolumePoint": {
        "type": "object",
        "description": "One bucket of the log volume: how many logs of each level it holds.",
        "required": [
          "bucket",
          "trace",
          "debug",
          "info",
          "warn",
          "error",
          "fatal"
        ],
        "properties": {
          "bucket": {
            "type": "string",
            "format": "date-time",
            "description": "Where the bucket starts."
          },
          "debug": {
            "type": "integer",
            "format": "int64"
          },
          "error": {
            "type": "integer",
            "format": "int64"
          },
          "fatal": {
            "type": "integer",
            "format": "int64"
          },
          "info": {
            "type": "integer",
            "format": "int64"
          },
          "trace": {
            "type": "integer",
            "format": "int64"
          },
          "warn": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "LoginRequest": {
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        }
      },
      "ManifestRequest": {
        "type": "object",
        "properties": {
          "organization": {
            "type": [
              "string",
              "null"
            ],
            "description": "Create the app under this organization instead of the user's account."
          }
        }
      },
      "ManifestResponse": {
        "type": "object",
        "description": "What the dashboard posts to GitHub to create the app.",
        "required": [
          "action_url",
          "manifest"
        ],
        "properties": {
          "action_url": {
            "type": "string",
            "description": "The form's `action`."
          },
          "manifest": {
            "type": "string",
            "description": "The form's one field, `manifest`."
          }
        }
      },
      "McpSettings": {
        "type": "object",
        "description": "Turns `/mcp` on or off: the body of `PUT /api/settings/mcp`.",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "McpStatus": {
        "type": "object",
        "description": "Whether `/mcp` answers, and the URL to give an assistant.",
        "required": [
          "enabled",
          "url"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The configured endpoint (`PUBLIC_URL` + `/mcp`), which OAuth checks\nthe resource against; the browser's own origin may differ. `null`\nwithout `PUBLIC_URL`, when signing in is off."
          }
        }
      },
      "MemberCandidate": {
        "type": "object",
        "description": "Someone who can be made a member.",
        "required": [
          "id",
          "email"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "MemberCandidates": {
        "type": "object",
        "description": "What the caller can choose from when setting a member's roles.",
        "required": [
          "users",
          "roles"
        ],
        "properties": {
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoleRef"
            }
          },
          "users": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MemberCandidate"
            }
          }
        }
      },
      "MemberRole": {
        "type": "object",
        "description": "A role someone holds on a project.",
        "required": [
          "id",
          "name",
          "inherited"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "inherited": {
            "type": "boolean",
            "description": "Held on every project: removing them from this one leaves it in place."
          },
          "name": {
            "type": "string"
          }
        }
      },
      "MetricDelta": {
        "type": "object",
        "description": "A counter measured over the requested window alongside the same counter\nover the window immediately before it.\n\n`previous` is `None` when the request asked for all time: there is no\nearlier window to compare against, and reporting `0` there would render as\na misleading \"+100%\" in the UI.",
        "required": [
          "current",
          "previous"
        ],
        "properties": {
          "current": {
            "type": "integer",
            "format": "int64"
          },
          "previous": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        }
      },
      "MonitorConfig": {
        "type": "object",
        "description": "A validated monitor configuration, with every default filled in.",
        "required": [
          "schedule",
          "checkin_margin",
          "max_runtime",
          "timezone",
          "failure_issue_threshold",
          "recovery_threshold"
        ],
        "properties": {
          "checkin_margin": {
            "type": "integer",
            "format": "int32",
            "description": "Minutes.",
            "minimum": 0
          },
          "failure_issue_threshold": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "max_runtime": {
            "type": "integer",
            "format": "int32",
            "description": "Minutes.",
            "minimum": 0
          },
          "recovery_threshold": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "schedule": {
            "$ref": "#/components/schemas/Schedule"
          },
          "timezone": {
            "type": "string",
            "description": "IANA name."
          }
        }
      },
      "MonitorConfigInput": {
        "type": "object",
        "description": "`monitor_config` as an SDK or the dashboard sends it: every field optional.",
        "properties": {
          "checkin_margin": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "failure_issue_threshold": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "max_runtime": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "recovery_threshold": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "schedule": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Schedule"
              },
              {
                "type": "null"
              }
            ]
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "MonitorEnvironmentResponse": {
        "type": "object",
        "description": "One environment of a monitor, with its most recent check-ins for the\ntimeline.",
        "required": [
          "id",
          "environment",
          "status",
          "next_checkin",
          "next_checkin_latest",
          "last_checkin",
          "recent_checkins"
        ],
        "properties": {
          "environment": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "last_checkin": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "next_checkin": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "next_checkin_latest": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "recent_checkins": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CheckInResponse"
            },
            "description": "Newest first."
          },
          "status": {
            "$ref": "#/components/schemas/MonitorEnvironmentStatus"
          }
        }
      },
      "MonitorEnvironmentStats": {
        "type": "object",
        "description": "One environment of a monitor over a window, bucket by bucket: what\n`GET /monitor-stats` returns, Sentry's `monitors-stats`.",
        "required": [
          "monitor_slug",
          "monitor_environment_id",
          "environment",
          "buckets"
        ],
        "properties": {
          "buckets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MonitorStatsBucket"
            },
            "description": "Oldest first, every environment of the response on the same axis."
          },
          "environment": {
            "type": "string"
          },
          "monitor_environment_id": {
            "type": "string",
            "format": "uuid"
          },
          "monitor_slug": {
            "type": "string"
          }
        }
      },
      "MonitorEnvironmentStatus": {
        "type": "string",
        "description": "Health of one monitor environment.",
        "enum": [
          "active",
          "ok",
          "error"
        ]
      },
      "MonitorResponse": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "config",
          "is_muted",
          "created_at",
          "environments"
        ],
        "properties": {
          "config": {
            "$ref": "#/components/schemas/MonitorConfig"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "environments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MonitorEnvironmentResponse"
            }
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "is_muted": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "MonitorStatsBucket": {
        "type": "object",
        "description": "The check-ins of one bucket, counted by status.",
        "required": [
          "bucket",
          "ok",
          "error",
          "missed",
          "timeout",
          "in_progress",
          "avg_duration_ms",
          "duration_count"
        ],
        "properties": {
          "avg_duration_ms": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Mean duration of the bucket's check-ins that reported one."
          },
          "bucket": {
            "type": "string",
            "format": "date-time",
            "description": "Where the bucket starts."
          },
          "duration_count": {
            "type": "integer",
            "format": "int64",
            "description": "How many check-ins reported a duration: the mean's weight when buckets\nare averaged together."
          },
          "error": {
            "type": "integer",
            "format": "int64"
          },
          "in_progress": {
            "type": "integer",
            "format": "int64"
          },
          "missed": {
            "type": "integer",
            "format": "int64"
          },
          "ok": {
            "type": "integer",
            "format": "int64"
          },
          "timeout": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "MyAccess": {
        "type": "object",
        "description": "What the caller may do. An owner may do everything and gets empty lists.",
        "required": [
          "is_owner",
          "instance",
          "all_projects",
          "projects"
        ],
        "properties": {
          "all_projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            },
            "description": "Project permissions held on every project."
          },
          "instance": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            },
            "description": "Workspace permissions."
          },
          "is_owner": {
            "type": "boolean"
          },
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectPermissions"
            },
            "description": "Project permissions held on one project."
          }
        }
      },
      "OAuthGrant": {
        "type": "object",
        "description": "A connected client, as its user sees it.",
        "required": [
          "id",
          "client_id",
          "client_name",
          "created_at"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "OrgDetails": {
        "type": "object",
        "description": "Synthetic organization sentry-cli checks before uploading.",
        "required": [
          "slug",
          "name",
          "id",
          "features"
        ],
        "properties": {
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "Permission": {
        "type": "object",
        "description": "One `(resource, action)` grant.",
        "required": [
          "resource",
          "action"
        ],
        "properties": {
          "action": {
            "$ref": "#/components/schemas/Action"
          },
          "resource": {
            "$ref": "#/components/schemas/Resource"
          }
        }
      },
      "PersonalAccess": {
        "type": "object",
        "description": "Permissions given to one person directly, without a role of the list.",
        "required": [
          "permissions"
        ],
        "properties": {
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            }
          },
          "project_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "Where its project permissions apply. Omitted or `null`: every project."
          }
        }
      },
      "PreviewSchedule": {
        "type": "object",
        "description": "Body of `POST /api/schedules/preview`.",
        "required": [
          "schedule"
        ],
        "properties": {
          "schedule": {
            "$ref": "#/components/schemas/Schedule"
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ],
            "description": "IANA zone the schedule is read in. Defaults to UTC."
          }
        }
      },
      "PreviewTemplateBody": {
        "type": "object",
        "description": "Body of a template preview request.",
        "required": [
          "template"
        ],
        "properties": {
          "template": {
            "type": "string"
          }
        }
      },
      "PreviewTemplateResponse": {
        "type": "object",
        "description": "`rendered` when `ok`, `error` otherwise.",
        "required": [
          "ok"
        ],
        "properties": {
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "ok": {
            "type": "boolean"
          },
          "rendered": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Product": {
        "type": "string",
        "description": "A kind of data a project can keep, and a route in its sidebar.\n\nTurning one off is not a view setting: its items are dropped at ingest,\nwith a 200 as Relay drops filtered data, so nothing new is stored and the\nSDK does not retry. What was already stored stays.",
        "enum": [
          "issues",
          "feedback",
          "releases",
          "performance",
          "agents",
          "logs",
          "crons"
        ]
      },
      "ProjectAge": {
        "type": "object",
        "required": [
          "project_id",
          "events",
          "transactions",
          "logs"
        ],
        "properties": {
          "events": {
            "$ref": "#/components/schemas/KindAge"
          },
          "logs": {
            "$ref": "#/components/schemas/KindAge"
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          },
          "transactions": {
            "$ref": "#/components/schemas/KindAge",
            "description": "Transactions; their spans are as old."
          }
        }
      },
      "ProjectListStats": {
        "type": "object",
        "description": "The at-a-glance aggregates one row of the project-list table needs.\n\nDeliberately narrower than [`ProjectStatsSummary`]: that one answers \"how\nis this project doing\" for a page dedicated to a single project, this one\nanswers \"which of my projects should I look at first\" and must stay cheap\nenough to compute for every project on the page at once.",
        "required": [
          "trend",
          "events",
          "new_issues",
          "open_issues",
          "fatal_issues"
        ],
        "properties": {
          "events": {
            "$ref": "#/components/schemas/MetricDelta",
            "description": "Error events in the window, against the window before it."
          },
          "fatal_issues": {
            "type": "integer",
            "format": "int64",
            "description": "The subset of `open_issues` at `fatal` level."
          },
          "new_issues": {
            "$ref": "#/components/schemas/MetricDelta",
            "description": "Issues whose `first_seen` falls in the window, against the window\nbefore it. Drives the \"issues are climbing\" signal, which event volume\ncannot give: one noisy issue can multiply events without anything new\nhaving broken."
          },
          "open_issues": {
            "type": "integer",
            "format": "int64",
            "description": "Issues currently unresolved, regardless of window."
          },
          "trend": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            },
            "description": "Distinct issues that received at least one event in each bucket, oldest\nfirst. Always `LIST_TREND_BUCKETS` long so the sparkline column renders\nat a constant width whatever window was asked for.\n\nCounts issues *active* in the bucket rather than issues *created* in\nit. Creations are far too sparse to draw: a quiet self-hosted project\nopens a handful of issues a day, which over 24 hourly buckets is three\nlone bars in a field of zeros. Deliberately not summable — an issue\nfiring all day is counted in every bucket it appears in, so the series\nis a shape, not a total."
          }
        }
      },
      "ProjectMember": {
        "type": "object",
        "description": "A member of one project: someone holding a role on it or on every project.",
        "required": [
          "user_id",
          "email",
          "roles"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MemberRole"
            }
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ProjectPermissions": {
        "type": "object",
        "required": [
          "project_id",
          "permissions"
        ],
        "properties": {
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            }
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ProjectRepository": {
        "type": "object",
        "required": [
          "project_id",
          "installation_id",
          "repo_full_name",
          "default_branch",
          "html_url",
          "code_mappings",
          "auto_create_issues",
          "auto_create_conditions",
          "codeowners_rules",
          "codeowners_synced_at",
          "issue_template"
        ],
        "properties": {
          "auto_create_conditions": {
            "type": "object"
          },
          "auto_create_issues": {
            "type": "boolean",
            "description": "Open a GitHub issue for new issues that pass `auto_create_conditions`."
          },
          "code_mappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodeMapping"
            }
          },
          "codeowners_rules": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How many ownership rules the last CODEOWNERS sync found; `None` before\nthe first sync.",
            "minimum": 0
          },
          "codeowners_synced_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "default_branch": {
            "type": "string"
          },
          "html_url": {
            "type": "string"
          },
          "installation_id": {
            "type": "integer",
            "format": "int64"
          },
          "issue_template": {
            "$ref": "#/components/schemas/IssueTemplate",
            "description": "Goes on top of the instance's template."
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          },
          "repo_full_name": {
            "type": "string"
          }
        }
      },
      "ProjectResponse": {
        "type": "object",
        "description": "Response with DSN included",
        "required": [
          "id",
          "name",
          "slug",
          "sentry_key",
          "dsn",
          "stored_event_count",
          "digested_event_count",
          "rate_limited_event_count",
          "rate_limit_per_minute",
          "rate_limit_per_hour",
          "created_at",
          "updated_at",
          "platform",
          "disabled_products",
          "product_order"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "digested_event_count": {
            "type": "integer",
            "format": "int32"
          },
          "disabled_products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "description": "Products whose data this project drops at ingest."
          },
          "dsn": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "platform": {
            "type": [
              "string",
              "null"
            ]
          },
          "product_order": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "description": "The order its sidebar lists the products in; the ones missing follow\nin their default order."
          },
          "rate_limit_per_hour": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "rate_limit_per_minute": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "The project's own limits, or `null` when it follows the operator's."
          },
          "rate_limited_event_count": {
            "type": "integer",
            "format": "int64",
            "description": "Events the quota dropped after ingest had accepted them."
          },
          "sentry_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "The DSN's public key: its 32 hex digits in hyphenated UUID form\n(8-4-4-4-12), not necessarily an RFC 4122 UUID. The DSN carries the\nsame key without hyphens.\n\n`null` without `client-keys:read` on the project, as is `dsn`."
          },
          "slug": {
            "type": "string"
          },
          "stats": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ProjectListStats",
                "description": "Present only when the request asked for `?stats_period=`.\n\nAbsent rather than zeroed when unrequested: a caller that did not ask\nmust be able to tell \"no stats were computed\" from \"this project is\nquiet\", and only one of those should render an empty sparkline."
              },
              {
                "type": "null"
              }
            ]
          },
          "stored_event_count": {
            "type": "integer",
            "format": "int32"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ProjectRetention": {
        "type": "object",
        "description": "A project that keeps its data for other windows than the defaults. Every\nkind is set: an override replaces the defaults whole.",
        "required": [
          "project_id",
          "events_days",
          "transactions_days",
          "logs_days"
        ],
        "properties": {
          "events_days": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "logs_days": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          },
          "transactions_days": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        }
      },
      "ProjectStatsSummary": {
        "type": "object",
        "description": "Project-wide counters for the overview page, each with its previous-period\ncomparison.",
        "required": [
          "period_hours",
          "events",
          "new_issues",
          "open_issues"
        ],
        "properties": {
          "events": {
            "$ref": "#/components/schemas/MetricDelta",
            "description": "Error events ingested in the window."
          },
          "new_issues": {
            "$ref": "#/components/schemas/MetricDelta",
            "description": "Issues whose `first_seen` falls in the window."
          },
          "open_issues": {
            "type": "integer",
            "format": "int64",
            "description": "Issues currently unresolved, regardless of window."
          },
          "period_hours": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "The resolved window in hours, or `None` for all time."
          }
        }
      },
      "ProjectStorage": {
        "type": "object",
        "description": "Per-project storage breakdown, one row per project (including empty ones).\n\nCounts are exact. `estimated_bytes` estimates the JSON payload length this\nproject holds across events, transactions, spans and logs: a sample of its\nnewest rows per table (spans, which have no ingest time, are sampled in no\nparticular order), scaled by the row count. It is exact for a project with\nno more rows than the sample.",
        "required": [
          "project_id",
          "project_name",
          "events_count",
          "transactions_count",
          "spans_count",
          "logs_count",
          "source_maps_count",
          "estimated_bytes",
          "events_bytes",
          "transactions_bytes",
          "logs_bytes"
        ],
        "properties": {
          "estimated_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "`events_bytes + transactions_bytes + logs_bytes`."
          },
          "events_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Events with their attachments."
          },
          "events_count": {
            "type": "integer",
            "format": "int64"
          },
          "logs_bytes": {
            "type": "integer",
            "format": "int64"
          },
          "logs_count": {
            "type": "integer",
            "format": "int64"
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          },
          "project_name": {
            "type": "string"
          },
          "source_maps_count": {
            "type": "integer",
            "format": "int64"
          },
          "spans_count": {
            "type": "integer",
            "format": "int64"
          },
          "transactions_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Transactions with their spans."
          },
          "transactions_count": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ProviderType": {
        "type": "string",
        "description": "Type of notification provider (replaces ChannelType)",
        "enum": [
          "webhook",
          "email",
          "slack",
          "custom_webhook"
        ]
      },
      "RateLimitsResponse": {
        "type": "object",
        "description": "Configure project routes\nThe server's per-project event limits (`MAX_EVENTS_PER_PROJECT_*`).",
        "required": [
          "project_per_minute",
          "project_per_hour"
        ],
        "properties": {
          "project_per_hour": {
            "type": "integer",
            "format": "int64"
          },
          "project_per_minute": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ReadinessChecks": {
        "type": "object",
        "required": [
          "database"
        ],
        "properties": {
          "database": {
            "type": "string"
          }
        }
      },
      "ReadinessResponse": {
        "type": "object",
        "required": [
          "status",
          "checks"
        ],
        "properties": {
          "checks": {
            "$ref": "#/components/schemas/ReadinessChecks"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "ReleaseHealthRow": {
        "type": "object",
        "description": "Per-release health row returned by the stats endpoint.",
        "required": [
          "release",
          "environment",
          "total",
          "errored",
          "crashed",
          "abnormal",
          "healthy",
          "crash_free_sessions_rate",
          "crash_free_users_rate"
        ],
        "properties": {
          "abnormal": {
            "type": "integer",
            "format": "int64"
          },
          "crash_free_sessions_rate": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "crash_free_users_rate": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "crashed": {
            "type": "integer",
            "format": "int64"
          },
          "environment": {
            "type": "string"
          },
          "errored": {
            "type": "integer",
            "format": "int64"
          },
          "healthy": {
            "type": "integer",
            "format": "int64"
          },
          "release": {
            "type": "string"
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ReleaseResponse": {
        "type": "object",
        "description": "API response for a release.",
        "required": [
          "version",
          "ref",
          "url",
          "dateCreated",
          "dateReleased"
        ],
        "properties": {
          "dateCreated": {
            "type": "string",
            "format": "date-time"
          },
          "dateReleased": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "version": {
            "type": "string"
          }
        }
      },
      "ReleaseSummary": {
        "type": "object",
        "description": "One release as the releases page reads it: its record, if CI created\none, and what it brought -- events, new issues, environments and session\nhealth -- the shape of Sentry's release list with `health=1`.\n\nCounts and rates cover the asked window and environment; the dates do not,\nso a release keeps its age however narrow the window.",
        "required": [
          "version",
          "date_created",
          "date_released",
          "ref",
          "url",
          "first_event",
          "last_event",
          "event_count",
          "new_issues",
          "environments",
          "sessions",
          "crashed",
          "crash_free_sessions",
          "crash_free_users",
          "adoption"
        ],
        "properties": {
          "adoption": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Its share of every release's sessions in the window, 0 to 1."
          },
          "crash_free_sessions": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "crash_free_users": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "crashed": {
            "type": "integer",
            "format": "int64"
          },
          "date_created": {
            "type": "string",
            "format": "date-time",
            "description": "The record's, else the first time the release was seen."
          },
          "date_released": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "environments": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Where it ran, from its events and its sessions."
          },
          "event_count": {
            "type": "integer",
            "format": "int64"
          },
          "first_event": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_event": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "new_issues": {
            "type": "integer",
            "format": "int64",
            "description": "Error issues first seen in it."
          },
          "ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "sessions": {
            "type": "integer",
            "format": "int64"
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "version": {
            "type": "string"
          }
        }
      },
      "RepoCommit": {
        "type": "object",
        "required": [
          "repo_full_name",
          "sha",
          "message",
          "author_name",
          "author_login",
          "url",
          "committed_at"
        ],
        "properties": {
          "author_login": {
            "type": [
              "string",
              "null"
            ]
          },
          "author_name": {
            "type": "string"
          },
          "committed_at": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": "string"
          },
          "repo_full_name": {
            "type": "string"
          },
          "sha": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        }
      },
      "Resource": {
        "type": "string",
        "description": "Every resource a permission can name.",
        "enum": [
          "projects",
          "users",
          "invitations",
          "roles",
          "api-tokens",
          "integrations",
          "github-app",
          "storage",
          "mcp",
          "telemetry",
          "issues",
          "performance",
          "logs",
          "sessions",
          "releases",
          "source-maps",
          "alert-rules",
          "monitors",
          "project",
          "client-keys",
          "project-members",
          "project-github"
        ]
      },
      "RetentionResponse": {
        "type": "object",
        "required": [
          "settings",
          "next_run_at",
          "last_run"
        ],
        "properties": {
          "last_run": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/RetentionRun"
              },
              {
                "type": "null"
              }
            ]
          },
          "next_run_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "`null` while everything is kept forever, and for up to a minute after\nthe settings change."
          },
          "settings": {
            "$ref": "#/components/schemas/RetentionSettings"
          }
        }
      },
      "RetentionRun": {
        "type": "object",
        "description": "How the last retention cleanup went.",
        "required": [
          "started_at",
          "finished_at",
          "status",
          "removed",
          "error"
        ],
        "properties": {
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "removed": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/CleanupCounts"
              },
              {
                "type": "null"
              }
            ]
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "description": "`running`, `ok` or `error`."
          }
        }
      },
      "RetentionSettings": {
        "type": "object",
        "description": "Retention: how long each kind of data is kept, by default and per\nproject, and when the cleanup that enforces it runs. Stored as the\nsettings of the `storage_cleanup` scheduled job; a field left out takes\nits default. Keeping everything forever runs nothing.",
        "required": [
          "defaults",
          "overrides",
          "frequency",
          "hour",
          "weekday"
        ],
        "properties": {
          "defaults": {
            "$ref": "#/components/schemas/RetentionWindows",
            "default": {
              "events_days": null,
              "logs_days": null,
              "transactions_days": null
            }
          },
          "frequency": {
            "$ref": "#/components/schemas/CleanupFrequency",
            "default": "daily"
          },
          "hour": {
            "type": "integer",
            "format": "int32",
            "description": "Hour of the day it runs, UTC.",
            "default": 3,
            "maximum": 23,
            "minimum": 0
          },
          "overrides": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectRetention"
            },
            "default": []
          },
          "weekday": {
            "type": "integer",
            "format": "int32",
            "description": "Day a weekly cleanup runs, 0 = Sunday.",
            "default": 0,
            "maximum": 6,
            "minimum": 0
          }
        }
      },
      "RetentionWindows": {
        "type": "object",
        "description": "How long each kind of data is kept, in days. `None` keeps it forever.",
        "required": [
          "events_days",
          "transactions_days",
          "logs_days"
        ],
        "properties": {
          "events_days": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Error events, and the issues they leave empty.",
            "default": null
          },
          "logs_days": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "default": null
          },
          "transactions_days": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Transactions with their spans.",
            "default": null
          }
        }
      },
      "Role": {
        "type": "object",
        "description": "A named set of permissions, given to users by an assignment.",
        "required": [
          "id",
          "name",
          "description",
          "permissions",
          "assignment_count",
          "created_at"
        ],
        "properties": {
          "assignment_count": {
            "type": "integer",
            "format": "int64",
            "description": "How many assignments use this role."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "description": {
            "type": "string"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            }
          }
        }
      },
      "RoleAssignment": {
        "type": "object",
        "description": "A role given to a user. `project_id = null` reaches every project. A role's\nworkspace permissions apply wherever it is held.",
        "required": [
          "id",
          "user_id",
          "role_id",
          "role_name",
          "project_id",
          "is_personal",
          "created_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "is_personal": {
            "type": "boolean",
            "description": "The user's own permissions rather than a role of the list."
          },
          "project_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "role_id": {
            "type": "integer",
            "format": "int32"
          },
          "role_name": {
            "type": "string"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "RoleInput": {
        "type": "object",
        "required": [
          "name",
          "permissions"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            }
          }
        }
      },
      "RoleRef": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "Schedule": {
        "oneOf": [
          {
            "type": "object",
            "description": "A five-field crontab, or an alias such as `@daily`.",
            "required": [
              "value",
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "crontab"
                ]
              },
              "value": {
                "type": "string"
              }
            }
          },
          {
            "type": "object",
            "description": "Every `value` `unit`s, counted from the previous run.",
            "required": [
              "value",
              "unit",
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "interval"
                ]
              },
              "unit": {
                "$ref": "#/components/schemas/IntervalUnit"
              },
              "value": {
                "type": "integer",
                "format": "int32",
                "minimum": 0
              }
            }
          }
        ]
      },
      "SchedulePreview": {
        "type": "object",
        "description": "When a schedule runs next, computed by the code that runs it: monitors\nexpect their check-ins and scheduled jobs fire at exactly these instants.",
        "required": [
          "next_runs"
        ],
        "properties": {
          "next_runs": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "date-time"
            }
          }
        }
      },
      "Scope": {
        "type": "string",
        "description": "Whether a resource belongs to the workspace or to one project.",
        "enum": [
          "instance",
          "project"
        ]
      },
      "SeenResponse": {
        "type": "object",
        "required": [
          "has_seen"
        ],
        "properties": {
          "has_seen": {
            "type": "boolean"
          }
        }
      },
      "SentryEvent": {
        "type": "object",
        "description": "Subset of `EventSerializer` for an error event\n(`api/serializers/models/event.py`).",
        "required": [
          "id",
          "eventID",
          "groupID",
          "projectID",
          "entries",
          "message",
          "title",
          "platform",
          "type",
          "metadata",
          "tags",
          "culprit",
          "dateCreated",
          "dateReceived"
        ],
        "properties": {
          "culprit": {
            "type": "string"
          },
          "dateCreated": {
            "type": "string",
            "format": "date-time"
          },
          "dateReceived": {
            "type": "string",
            "format": "date-time"
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "eventID": {
            "type": "string"
          },
          "groupID": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "metadata": {
            "type": "object"
          },
          "platform": {
            "type": "string"
          },
          "projectID": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SentryTag"
            }
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        }
      },
      "SentryGroupProject": {
        "type": "object",
        "description": "`GroupProjectResponse` (`api/serializers/models/group.py`).",
        "required": [
          "id",
          "name",
          "slug",
          "platform"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "platform": {
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "SentryIssue": {
        "type": "object",
        "description": "Subset of `GroupSerializer` plus its seen stats\n(`api/serializers/models/group.py`), and `stats` when the caller asked\nfor a series (`StreamGroupSerializer`, `group_stream.py`).",
        "required": [
          "id",
          "shortId",
          "title",
          "culprit",
          "logger",
          "level",
          "status",
          "statusDetails",
          "substatus",
          "platform",
          "project",
          "type",
          "metadata",
          "issueType",
          "issueCategory",
          "priority",
          "count",
          "userCount",
          "firstSeen",
          "lastSeen",
          "annotations"
        ],
        "properties": {
          "annotations": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Links to external issues; Rustrak keeps none, so always empty."
          },
          "count": {
            "type": "string",
            "description": "`str(times_seen)`: Sentry sends the count as a string."
          },
          "culprit": {
            "type": "string"
          },
          "firstSeen": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "description": "The issue's `numeric_id`: Sentry's group ids are integers."
          },
          "issueCategory": {
            "type": "string"
          },
          "issueType": {
            "type": "string"
          },
          "lastSeen": {
            "type": "string",
            "format": "date-time"
          },
          "level": {
            "type": "string"
          },
          "logger": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": "object"
          },
          "platform": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": [
              "string",
              "null"
            ]
          },
          "project": {
            "$ref": "#/components/schemas/SentryGroupProject"
          },
          "shortId": {
            "type": "string"
          },
          "stats": {
            "type": [
              "object",
              "null"
            ],
            "description": "`[unix_ts, count]` per bucket, keyed by stats period."
          },
          "status": {
            "type": "string"
          },
          "statusDetails": {
            "type": "object"
          },
          "substatus": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "`error`, or `default` for an issue made of messages."
          },
          "userCount": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "SentryIssueDetails": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SentryIssue"
          },
          {
            "type": "object",
            "required": [
              "firstRelease",
              "lastRelease",
              "userReportCount"
            ],
            "properties": {
              "firstRelease": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/SentryRelease"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "lastRelease": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/SentryRelease"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "userReportCount": {
                "type": "integer",
                "format": "int64"
              }
            }
          }
        ],
        "description": "Subset of `GroupDetailsEndpoint`'s response\n(`issues/endpoints/group_details.py`)."
      },
      "SentryOrganization": {
        "type": "object",
        "description": "Subset of `OrganizationSummarySerializer`\n(`api/serializers/models/organization.py`).",
        "required": [
          "id",
          "slug",
          "name",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/SentryStatus"
          }
        }
      },
      "SentryProject": {
        "type": "object",
        "description": "Subset of `ProjectWithOrganizationSerializer`\n(`api/serializers/models/project.py`). Sentry's ids are strings.",
        "required": [
          "id",
          "slug",
          "name",
          "platform",
          "dateCreated",
          "status",
          "organization"
        ],
        "properties": {
          "dateCreated": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "organization": {
            "$ref": "#/components/schemas/SentryOrganization"
          },
          "platform": {
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "`STATUS_LABELS[ObjectStatus.ACTIVE]`: Rustrak only lists live projects."
          }
        }
      },
      "SentryRelease": {
        "type": "object",
        "description": "A release as `serialize_releases` (`api/helpers/group_index/index.py`)\nfalls back to it, with the serializer's `shortVersion`, which is the\nversion itself (`api/serializers/models/release.py`).",
        "required": [
          "version",
          "shortVersion"
        ],
        "properties": {
          "shortVersion": {
            "type": "string"
          },
          "version": {
            "type": "string"
          }
        }
      },
      "SentryStatus": {
        "type": "object",
        "description": "`{\"id\", \"name\"}` of a status, as Sentry nests it in an organization.",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "SentryTag": {
        "type": "object",
        "required": [
          "key",
          "value"
        ],
        "properties": {
          "key": {
            "type": "string"
          },
          "value": {
            "type": "string"
          }
        }
      },
      "SentryUserReport": {
        "type": "object",
        "description": "Body of a user report (`UserReportSerializer` in Sentry's\n`api/serializers/models/userreport.py`), as the report was received.",
        "required": [
          "id",
          "eventID",
          "name",
          "email",
          "comments",
          "dateCreated"
        ],
        "properties": {
          "comments": {
            "type": "string"
          },
          "dateCreated": {
            "type": "string",
            "format": "date-time"
          },
          "email": {
            "type": "string"
          },
          "eventID": {
            "type": "string",
            "description": "The error event the report is about."
          },
          "id": {
            "type": "string",
            "description": "The feedback the report became."
          },
          "name": {
            "type": "string"
          }
        }
      },
      "SentryUserReportRequest": {
        "type": "object",
        "description": "Request body of a user report.",
        "required": [
          "event_id"
        ],
        "properties": {
          "comments": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "event_id": {
            "type": "string",
            "description": "The error event the report is about."
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SessionSummary": {
        "type": "object",
        "description": "Project-wide session health summary, aggregated across all releases and environments.",
        "required": [
          "total",
          "errored",
          "crashed",
          "abnormal",
          "crash_free_sessions_rate",
          "crash_free_users_rate",
          "active_releases"
        ],
        "properties": {
          "abnormal": {
            "type": "integer",
            "format": "int64"
          },
          "active_releases": {
            "type": "integer",
            "format": "int64"
          },
          "crash_free_sessions_rate": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "crash_free_users_rate": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "crashed": {
            "type": "integer",
            "format": "int64"
          },
          "errored": {
            "type": "integer",
            "format": "int64"
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "SessionTimeseriesPoint": {
        "type": "object",
        "description": "One time-bucketed point in a project's session trend, aggregated across all\nreleases and environments. Powers trend charts (crash-free sessions over time).",
        "required": [
          "bucket",
          "total",
          "crashed",
          "crash_free_sessions_rate"
        ],
        "properties": {
          "bucket": {
            "type": "string",
            "format": "date-time"
          },
          "crash_free_sessions_rate": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "crashed": {
            "type": "integer",
            "format": "int64"
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "SetAccess": {
        "type": "object",
        "description": "Everything a user holds.",
        "required": [
          "assignments"
        ],
        "properties": {
          "assignments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AssignmentInput"
            }
          },
          "personal": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PersonalAccess",
                "description": "Omitted or `null`: no personal permissions."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "SetProjectMember": {
        "type": "object",
        "required": [
          "user_id",
          "role_ids"
        ],
        "properties": {
          "role_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "The member's roles on this project; empty removes them."
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "SortOrder": {
        "type": "string",
        "description": "Sort order direction",
        "enum": [
          "asc",
          "desc"
        ]
      },
      "SourceMapFile": {
        "type": "object",
        "required": [
          "debugId",
          "fileType",
          "size",
          "timesUsed",
          "dateUploaded"
        ],
        "properties": {
          "dateUploaded": {
            "type": "string"
          },
          "debugId": {
            "type": "string"
          },
          "fileType": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "format": "int32"
          },
          "timesUsed": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "SourceMapGcResult": {
        "type": "object",
        "description": "Outcome of a source-map garbage collection: orphaned `source_file` rows\n(no `source_file_metadata` referencing them) removed from the DB and unlinked\nfrom disk. `bytes_freed` is the exact summed `size` of the removed files.",
        "required": [
          "files_removed",
          "bytes_freed"
        ],
        "properties": {
          "bytes_freed": {
            "type": "integer",
            "format": "int64"
          },
          "files_removed": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "SourceMapList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SourceMapFile"
            }
          }
        }
      },
      "SourceMapStorage": {
        "type": "object",
        "description": "Exact source-map storage weight, summed from the `size` columns.\n\nSource maps live in two places: `chunk` holds the raw upload bytes as in-DB\nBYTEA, `source_file` holds the assembled artifact on the filesystem CAS. Both\ncarry a `size` column, so the weight is an exact SUM — no filesystem walk.",
        "required": [
          "chunk_bytes",
          "source_file_bytes",
          "total_bytes",
          "file_count"
        ],
        "properties": {
          "chunk_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes held in the in-DB `chunk` table (raw upload chunks)."
          },
          "file_count": {
            "type": "integer",
            "format": "int64",
            "description": "Number of `source_file` rows."
          },
          "source_file_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes held on disk via `source_file` (assembled artifacts)."
          },
          "total_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "`chunk_bytes + source_file_bytes`."
          }
        }
      },
      "SpanDetailResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SpanResponse"
          },
          {
            "type": "object",
            "required": [
              "attributes",
              "tags"
            ],
            "properties": {
              "attributes": {
                "type": "object",
                "description": "The span's attribute bag, flattened to `{key: value}` regardless of\nwhich producer wrote the row — see [`span_attributes`]. This is the\n`gen_ai.*` payload (prompts, responses, tool arguments and results,\nsystem instructions, tool definitions) that the agents UI renders."
              },
              "tags": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Span tags, when the producer stored any. Spans Protocol v2 has no\nseparate tags concept — everything is an attribute — so this is always\n`None` for a v2-origin span."
              }
            }
          }
        ],
        "description": "One span with its full attribute bag — the detail counterpart to\n[`SpanResponse`].\n\nThe list response deliberately omits attributes: `spans.data` is never\ntrimmed (unlike event data, which goes through `services::event_trim`), so\na single AI span can carry a whole prompt and a trace's worth of them would\ndwarf the waterfall it is drawn from. Attributes are fetched one span at a\ntime instead, which is also how Sentry's own agent drawer works — the span\nlist is light and the details panel loads the selected node's attributes."
      },
      "SpanResponse": {
        "type": "object",
        "description": "A single indexed span — extracted from a transaction, OR standalone\n(Sentry \"span\" item type). Both origins write into the same `spans`\ntable, so `transaction_id` is the only thing that distinguishes them.",
        "required": [
          "id",
          "transaction_id",
          "span_id",
          "trace_id",
          "parent_span_id",
          "op",
          "description",
          "status",
          "start_timestamp",
          "timestamp",
          "duration_ms",
          "exclusive_time_ms",
          "is_segment",
          "segment_id",
          "platform",
          "release",
          "environment",
          "gen_ai_operation_type",
          "gen_ai_agent_name",
          "gen_ai_request_model",
          "gen_ai_response_model",
          "gen_ai_tool_name",
          "gen_ai_conversation_id",
          "gen_ai_usage_input_tokens",
          "gen_ai_usage_output_tokens",
          "gen_ai_usage_total_tokens"
        ],
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Duration in milliseconds (timestamp - start_timestamp)."
          },
          "environment": {
            "type": [
              "string",
              "null"
            ]
          },
          "exclusive_time_ms": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Relay's exclusive (self) time in milliseconds, if provided by the SDK."
          },
          "gen_ai_agent_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "gen_ai_conversation_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "gen_ai_operation_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "gen_ai.* denormalized fields (story-ai-agent-monitoring.md, GH #180).\nAll `None` unless the span was recognized as an AI span."
          },
          "gen_ai_request_model": {
            "type": [
              "string",
              "null"
            ]
          },
          "gen_ai_response_model": {
            "type": [
              "string",
              "null"
            ]
          },
          "gen_ai_tool_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "gen_ai_usage_input_tokens": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "gen_ai_usage_output_tokens": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "gen_ai_usage_total_tokens": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "is_segment": {
            "type": "boolean"
          },
          "op": {
            "type": [
              "string",
              "null"
            ]
          },
          "parent_span_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set for every span. A standalone span reports its own; a\ntransaction-embedded one is stamped with its parent transaction's at\nwrite time, rather than being left NULL to be recovered by a JOIN —\nthe agents dashboard filters `spans` directly and a NULL would drop\nthe row from an environment-filtered view."
          },
          "release": {
            "type": [
              "string",
              "null"
            ]
          },
          "segment_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "span_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "start_timestamp": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "timestamp": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "trace_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "transaction_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The parent transaction, if this span was extracted from one.\n`None` for a standalone span."
          }
        }
      },
      "SsoConfigResponse": {
        "type": "object",
        "required": [
          "enabled",
          "provider_name",
          "password_login_enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "password_login_enabled": {
            "type": "boolean",
            "description": "Whether the login page should show the password form. False only when\nthe operator turned password sign-in off."
          },
          "provider_name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SsoLinkResponse": {
        "type": "object",
        "required": [
          "email",
          "provider_name"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "provider_name": {
            "type": "string"
          }
        }
      },
      "SsoStartResponse": {
        "type": "object",
        "required": [
          "authorization_url"
        ],
        "properties": {
          "authorization_url": {
            "type": "string"
          }
        }
      },
      "StorageAge": {
        "type": "object",
        "description": "The age of everything the instance holds, by project and kind, keyed on\ningest time like retention.",
        "required": [
          "bucket_days",
          "projects"
        ],
        "properties": {
          "bucket_days": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            },
            "description": "The buckets' upper bounds in days; the last bucket has none."
          },
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectAge"
            }
          }
        }
      },
      "StorageSummary": {
        "type": "object",
        "description": "Instance-wide storage summary: what Rustrak is holding right now.\n\nRow counts are exact (indexed `COUNT(*)`). `total_db_size_bytes` is a\nbest-effort figure from the backend (`pg_database_size` / SQLite page count),\nwhile `source_maps` is exact (summed `size` columns).",
        "required": [
          "total_db_size_bytes",
          "events_count",
          "transactions_count",
          "spans_count",
          "logs_count",
          "source_maps"
        ],
        "properties": {
          "events_count": {
            "type": "integer",
            "format": "int64"
          },
          "logs_count": {
            "type": "integer",
            "format": "int64"
          },
          "source_maps": {
            "$ref": "#/components/schemas/SourceMapStorage",
            "description": "Exact source-map weight + file count."
          },
          "spans_count": {
            "type": "integer",
            "format": "int64"
          },
          "total_db_size_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Whole-database size in bytes (best-effort, backend-reported)."
          },
          "transactions_count": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "SubscriptionResponse": {
        "type": "object",
        "required": [
          "is_subscribed"
        ],
        "properties": {
          "is_subscribed": {
            "type": "boolean"
          }
        }
      },
      "TagSummary": {
        "type": "object",
        "description": "A tag key with its most common values within an issue.",
        "required": [
          "key",
          "total_values",
          "top_values"
        ],
        "properties": {
          "key": {
            "type": "string"
          },
          "top_values": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TagValueCount"
            }
          },
          "total_values": {
            "type": "integer",
            "description": "The scanned events carrying the tag, whatever its value: Sentry's\n`totalValues` (`GroupTagKey.count`), so each top value's share is its\n`count` over this.",
            "minimum": 0
          }
        }
      },
      "TagValueCount": {
        "type": "object",
        "description": "A tag value with its event count within an issue.",
        "required": [
          "value",
          "count"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "format": "int64"
          },
          "value": {
            "type": "string"
          }
        }
      },
      "TeamMemberResponse": {
        "type": "object",
        "description": "A user as exposed on the team roster.",
        "required": [
          "id",
          "email",
          "role",
          "is_active",
          "is_primary",
          "created_at",
          "last_login"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "email": {
            "type": "string"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "is_active": {
            "type": "boolean"
          },
          "is_primary": {
            "type": "boolean",
            "description": "True for the first-registered (primary) account, which cannot be demoted\nor deleted."
          },
          "last_login": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "role": {
            "$ref": "#/components/schemas/UserRole"
          }
        }
      },
      "TelemetryPreview": {
        "type": "object",
        "required": [
          "enabled",
          "reason",
          "sink",
          "report"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why nothing is sent, when `enabled` is false."
          },
          "report": {
            "type": "object",
            "description": "The next heartbeat, exactly as it would leave. Shown even when\ndisabled, so the decision can be made on the real thing."
          },
          "sink": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where it goes, when `enabled` is true."
          }
        }
      },
      "TestChannelResponse": {
        "type": "object",
        "description": "Outcome of a test notification.",
        "required": [
          "success",
          "message",
          "response_body"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "response_body": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the endpoint answered, when it answered anything."
          },
          "success": {
            "type": "boolean"
          }
        }
      },
      "TestIntegrationBody": {
        "type": "object",
        "description": "Request body for the test-integration endpoint.",
        "properties": {
          "routing_override": {
            "type": [
              "object",
              "null"
            ]
          }
        }
      },
      "ToggleRequest": {
        "type": "object",
        "description": "Body for toggling a per-user flag (bookmark/subscription).",
        "properties": {
          "enabled": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "TransactionDetailResponse": {
        "type": "object",
        "description": "Response model for a single transaction detail view.\n\nCarries the same summary fields as [`TransactionResponse`] plus the full\nSentry payload under `data` (spans, contexts.trace, measurements, tags,\nrequest, user). The frontend builds the span waterfall and metrics view\nfrom `data`.",
        "required": [
          "id",
          "event_id",
          "transaction_name",
          "timestamp",
          "start_timestamp",
          "duration_ms",
          "platform",
          "environment",
          "release",
          "ingested_at",
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "description": "Full Sentry transaction payload (spans, contexts, measurements, tags, request, user)."
          },
          "duration_ms": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Duration in milliseconds (timestamp - start_timestamp). None if start_timestamp is missing."
          },
          "environment": {
            "type": "string"
          },
          "event_id": {
            "type": "string",
            "description": "Sentry event ID: 32 hex digits, not necessarily an RFC 4122 UUID."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ingested_at": {
            "type": "string",
            "format": "date-time"
          },
          "platform": {
            "type": "string"
          },
          "release": {
            "type": "string"
          },
          "start_timestamp": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "transaction_name": {
            "type": "string"
          }
        }
      },
      "TransactionResponse": {
        "type": "object",
        "description": "Response model for a single transaction in the list view",
        "required": [
          "id",
          "event_id",
          "transaction_name",
          "timestamp",
          "start_timestamp",
          "duration_ms",
          "platform",
          "environment",
          "release",
          "ingested_at",
          "status"
        ],
        "properties": {
          "duration_ms": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Duration in milliseconds (timestamp - start_timestamp). None if start_timestamp is missing."
          },
          "environment": {
            "type": "string"
          },
          "event_id": {
            "type": "string",
            "description": "Sentry event ID: 32 hex digits, not necessarily an RFC 4122 UUID."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ingested_at": {
            "type": "string",
            "format": "date-time"
          },
          "platform": {
            "type": "string"
          },
          "release": {
            "type": "string"
          },
          "start_timestamp": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Trace status (`ok`, `internal_error`...), if the SDK sent one."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "transaction_name": {
            "type": "string"
          }
        }
      },
      "TransactionStatsResponse": {
        "type": "object",
        "description": "Aggregate performance stats for one (transaction_name, op) group.\nPowers the performance overview: throughput + latency percentiles +\nfailure rate per transaction. Percentiles are continuous (linear\ninterpolation, matching Postgres `percentile_cont`).",
        "required": [
          "transaction_name",
          "op",
          "count",
          "p50_ms",
          "p95_ms",
          "p99_ms",
          "failure_rate",
          "avg_ms",
          "total_ms",
          "time_share",
          "last_seen"
        ],
        "properties": {
          "avg_ms": {
            "type": "number",
            "format": "double"
          },
          "count": {
            "type": "integer",
            "format": "int64",
            "description": "Number of transactions in this group."
          },
          "failure_rate": {
            "type": "number",
            "format": "double",
            "description": "Fraction (0.0–1.0) of transactions whose trace status is set and not \"ok\"."
          },
          "last_seen": {
            "type": "string",
            "format": "date-time"
          },
          "op": {
            "type": [
              "string",
              "null"
            ]
          },
          "p50_ms": {
            "type": "number",
            "format": "double"
          },
          "p95_ms": {
            "type": "number",
            "format": "double"
          },
          "p99_ms": {
            "type": "number",
            "format": "double"
          },
          "time_share": {
            "type": "number",
            "format": "double",
            "description": "Its share, 0 to 1, of the time every endpoint in the same read takes."
          },
          "total_ms": {
            "type": "number",
            "format": "double",
            "description": "Every sample's duration added up: how much time the endpoint takes in all."
          },
          "transaction_name": {
            "type": "string"
          }
        }
      },
      "TransactionTimeseriesPoint": {
        "type": "object",
        "description": "One bucket of an endpoint's trend: how often it ran, how often it failed\nand how long it took.",
        "required": [
          "bucket",
          "count",
          "failures",
          "p50_ms",
          "p95_ms"
        ],
        "properties": {
          "bucket": {
            "type": "string",
            "format": "date-time"
          },
          "count": {
            "type": "integer",
            "format": "int64"
          },
          "failures": {
            "type": "integer",
            "format": "int64"
          },
          "p50_ms": {
            "type": "number",
            "format": "double"
          },
          "p95_ms": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "UpdateAlertIntegration": {
        "type": "object",
        "description": "DTO for updating an alert integration",
        "properties": {
          "credentials": {
            "type": [
              "object",
              "null"
            ]
          },
          "is_enabled": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpdateAlertRule": {
        "type": "object",
        "description": "DTO for updating an alert rule",
        "properties": {
          "alert_type": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AlertType",
                "description": "What the rule fires on; rules are independent, so any trigger may change."
              },
              {
                "type": "null"
              }
            ]
          },
          "channels": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/AlertRuleChannelInput"
            }
          },
          "conditions": {
            "type": [
              "object",
              "null"
            ]
          },
          "cooldown_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "is_enabled": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpdateIssueState": {
        "type": "object",
        "description": "Request to update issue state.\n\n`status`/`substatus`/`priority`/assignment are the canonical fields.\n`is_resolved`/`is_muted` are accepted as a deprecated compatibility shim\nand mapped onto `status`.",
        "properties": {
          "assigned_to": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "`None` when omitted, `Some(None)` when the client sent an explicit\n`null` (clears the assignment), `Some(Some(id))` to assign."
          },
          "assignee_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_muted": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_resolved": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "priority": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/IssuePriority"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/IssueStatusUpdate"
              },
              {
                "type": "null"
              }
            ]
          },
          "substatus": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpdateMonitor": {
        "type": "object",
        "description": "Body of `PUT /api/projects/{project_id}/monitors/{slug}`. Fields left out\nkeep their value, including each field of `config`.",
        "properties": {
          "config": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/MonitorConfigInput"
              },
              {
                "type": "null"
              }
            ]
          },
          "is_muted": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpdatePreferencesRequest": {
        "type": "object",
        "description": "What a reader may change about how the dashboard is presented to them.\n\nEvery field is doubly optional, and both levels are used: absent means\n\"leave it\", `null` means \"clear it\". `#[serde(default)]` with\n`deserialize_with` is what keeps those distinguishable, because plain\n`Option<Option<T>>` collapses a missing key and an explicit null.",
        "properties": {
          "language": {
            "type": [
              "string",
              "null"
            ]
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpdateProject": {
        "type": "object",
        "description": "DTO for updating a project",
        "properties": {
          "disabled_products": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "description": "The products to stop storing, replacing the current list. `issues`\ncannot be one of them (400). Data already stored is kept."
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "type": [
              "string",
              "null"
            ],
            "description": "Manual override of the project's platform, such as `python-django` or\n`javascript-nextjs`. Rejected with a 400 if it is not one of the\nsupported values.\n\nThe supported set is wider than the platforms an event may declare, so\nframework-specific identifiers are accepted here. An update overwrites\nany auto-assigned value, which is how a wrong detection is corrected.\nSending `null` leaves the current value untouched rather than clearing\nit."
          },
          "product_order": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "description": "The sidebar's order of products, replacing the current one."
          },
          "rate_limit_per_hour": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "The same for the hour, against `MAX_EVENTS_PER_PROJECT_PER_HOUR`."
          },
          "rate_limit_per_minute": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "The project's own events-per-minute limit. It can only tighten the\noperator's `MAX_EVENTS_PER_PROJECT_PER_MINUTE`, never raise it.\nAbsent leaves it as it is; `null` removes it."
          },
          "slug": {
            "type": [
              "string",
              "null"
            ],
            "description": "New slug, slugified before storing.\n\nA slug already taken by another project returns a 409. It is not\nsilently de-duplicated the way a slug derived at creation time is,\nsince storing something other than what was requested would be wrong.\n\nSending `null` leaves the current value untouched."
          }
        }
      },
      "UpdateProjectRepository": {
        "type": "object",
        "required": [
          "installation_id",
          "repo_full_name"
        ],
        "properties": {
          "auto_create_conditions": {
            "type": [
              "object",
              "null"
            ],
            "description": "The same filters an alert rule takes: `min_level`, `environments`,\n`min_events`."
          },
          "auto_create_issues": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "code_mappings": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/CodeMapping"
            }
          },
          "installation_id": {
            "type": "integer",
            "format": "int64"
          },
          "issue_template": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/IssueTemplate"
              },
              {
                "type": "null"
              }
            ]
          },
          "repo_full_name": {
            "type": "string"
          }
        }
      },
      "UpdateRelease": {
        "type": "object",
        "description": "DTO for `PUT .../releases/{version}/` — generic partial update.\nSetting `date_released` IS \"finalize\": there is no separate status flag.\nAbsent fields (including an explicit `null`) leave the stored value\nunchanged, matching Sentry's own partial-update semantics for this endpoint.",
        "properties": {
          "dateReleased": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpdateUserRole": {
        "type": "object",
        "description": "Request body for changing a user's global role.",
        "required": [
          "role"
        ],
        "properties": {
          "role": {
            "$ref": "#/components/schemas/UserRole"
          }
        }
      },
      "UserAccess": {
        "type": "object",
        "description": "Everything a user holds.",
        "required": [
          "assignments",
          "personal_permissions"
        ],
        "properties": {
          "assignments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoleAssignment"
            }
          },
          "personal_permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            },
            "description": "What their personal role holds; its places are in `assignments`."
          }
        }
      },
      "UserReport": {
        "type": "object",
        "description": "A user feedback report attached to a project/issue/event.",
        "required": [
          "id",
          "project_id",
          "issue_id",
          "event_id",
          "name",
          "email",
          "comments",
          "created_at"
        ],
        "properties": {
          "comments": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "email": {
            "type": "string"
          },
          "event_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "issue_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "project_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "UserReportRequest": {
        "type": "object",
        "description": "Body for submitting user feedback on an issue.",
        "properties": {
          "comments": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "event_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UserResponse": {
        "type": "object",
        "required": [
          "id",
          "email",
          "role",
          "is_admin",
          "language",
          "timezone"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "is_admin": {
            "type": "boolean",
            "description": "Convenience flag derived from `role` (kept for backward compatibility)."
          },
          "language": {
            "type": [
              "string",
              "null"
            ],
            "description": "Chosen dashboard language, or `null` when the user never chose one."
          },
          "role": {
            "$ref": "#/components/schemas/UserRole"
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Chosen IANA timezone, or `null` when the user never chose one."
          }
        }
      },
      "UserRole": {
        "type": "string",
        "description": "Instance-wide role for a user.\n\n`Admin` has full access to every project and to team management.\n`Member` only sees projects they are a member of (see `ProjectRole`).",
        "enum": [
          "admin",
          "member"
        ]
      },
      "VersionResponse": {
        "type": "object",
        "required": [
          "version"
        ],
        "properties": {
          "version": {
            "type": "string"
          }
        }
      }
    },
    "securitySchemes": {
      "bearer_auth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "40-char hex token"
      },
      "session_cookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "session"
      }
    }
  }
}