{"openapi":"3.0.3","info":{"title":"MarBoba Public REST API","version":"1.0.0","description":"Public REST API for MarBoba. Authenticate with a Personal Access Token from Settings → Personal Access Tokens.","contact":{"name":"MarBoba","url":"https://marboba.com"}},"servers":[{"url":"https://api.marboba.com/v1","description":"Production"},{"url":"https://api-dev.marboba.com/v1","description":"Development"}],"components":{"securitySchemes":{"BearerPAT":{"type":"http","scheme":"bearer","bearerFormat":"Personal Access Token","description":"Personal Access Token. Format: `mb_pat_live_<48-hex-chars>` for production, `mb_pat_test_<48-hex-chars>` for test mode."}},"schemas":{"Project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"githubUrl":{"type":"string","nullable":true},"repoUrl":{"type":"string","nullable":true},"vcsConnectionId":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","archived"]},"Team":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"color":{"type":"string","nullable":true},"slackChannel":{"type":"string","nullable":true},"leadUid":{"type":"string","nullable":true},"memberUids":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","memberUids"]},"Api":{"type":"object","description":"A first-class API entry in the service catalog. Sibling to Project and Team.","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"componentId":{"type":"string","nullable":true,"description":"Owning component (project) id, or null if unowned."},"ownerTeamId":{"type":"string","nullable":true},"kind":{"type":"string","enum":["rest","graphql","grpc","asyncapi","openapi","other"]},"lifecycle":{"type":"string","enum":["experimental","production","deprecated","retired"]},"specUrl":{"type":"string","nullable":true,"description":"Pointer to a hosted OpenAPI/GraphQL/proto spec; used by the docs UI."},"tags":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","kind","lifecycle","tags"]},"ApiInput":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"componentId":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"kind":{"type":"string","enum":["rest","graphql","grpc","asyncapi","openapi","other"]},"lifecycle":{"type":"string","enum":["experimental","production","deprecated","retired"]},"specUrl":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}}}},"Resource":{"type":"object","description":"A piece of stateful infrastructure registered in the catalog — database, queue, bucket, cache, etc.","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"componentId":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"kind":{"type":"string","enum":["database","queue","bucket","cache","secret_store","topic","function","load_balancer","cdn","other"]},"provider":{"type":"string","enum":["aws","gcp","azure","firebase","cloudflare","vercel","supabase","planetscale","neon","other"]},"lifecycle":{"type":"string","enum":["experimental","production","deprecated","retired"]},"consoleUrl":{"type":"string","nullable":true,"description":"Deep link into the cloud provider's console."},"externalId":{"type":"string","nullable":true,"description":"Provider's ARN/URI/qualified name for this resource."},"tags":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","kind","provider","lifecycle","tags"]},"ResourceInput":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"componentId":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"kind":{"type":"string","enum":["database","queue","bucket","cache","secret_store","topic","function","load_balancer","cdn","other"]},"provider":{"type":"string","enum":["aws","gcp","azure","firebase","cloudflare","vercel","supabase","planetscale","neon","other"]},"lifecycle":{"type":"string","enum":["experimental","production","deprecated","retired"]},"consoleUrl":{"type":"string","nullable":true},"externalId":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}}}},"System":{"type":"object","description":"A logical grouping of components, APIs, and resources. Sibling to Domain (a System's parent) and to leaf-entity kinds.","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"domainId":{"type":"string","nullable":true,"description":"Parent domain id, or null for top-level systems."},"lifecycle":{"type":"string","enum":["experimental","production","deprecated","retired"]},"componentIds":{"type":"array","items":{"type":"string"}},"apiIds":{"type":"array","items":{"type":"string"}},"resourceIds":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","lifecycle","componentIds","apiIds","resourceIds","tags"]},"SystemInput":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"domainId":{"type":"string","nullable":true},"lifecycle":{"type":"string","enum":["experimental","production","deprecated","retired"]},"componentIds":{"type":"array","items":{"type":"string"}},"apiIds":{"type":"array","items":{"type":"string"}},"resourceIds":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}}}},"Domain":{"type":"object","description":"Top-level grouping in the catalog hierarchy: Domain → System → leaf entities.","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","tags"]},"DomainInput":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}}}},"DependencyEdge":{"type":"object","description":"A directed `dependsOn` edge between two catalog entities. Edges are immutable; to change one, delete and re-create.","properties":{"id":{"type":"string"},"fromKind":{"type":"string","enum":["component","api","resource","system","domain"]},"fromId":{"type":"string"},"toKind":{"type":"string","enum":["component","api","resource","system","domain"]},"toId":{"type":"string"},"type":{"type":"string","description":"Edge type. Default `depends_on`. Common values: depends_on, consumes_api, provides_api, calls, reads_from, writes_to."},"description":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","fromKind","fromId","toKind","toId","type"]},"DependencyEdgeInput":{"type":"object","properties":{"fromKind":{"type":"string","enum":["component","api","resource","system","domain"]},"fromId":{"type":"string"},"toKind":{"type":"string","enum":["component","api","resource","system","domain"]},"toId":{"type":"string"},"type":{"type":"string"},"description":{"type":"string","nullable":true}},"required":["fromKind","fromId","toKind","toId"]},"Secret":{"type":"object","description":"Vault item metadata. The encrypted `value` is **never** returned by /v1 — this surface is metadata-only. `admin` scope (PAT only) is required because even the names of secrets are sensitive.","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","description":"Vault item type (`text`, `file`, `keystore`, etc.)."},"category":{"type":"string","nullable":true},"keyword":{"type":"string","nullable":true},"deploymentOnly":{"type":"boolean"},"maskedPreview":{"type":"string","nullable":true,"description":"First few characters of the secret followed by `…`. Safe to log; useful for spotting the right secret without unsealing it."},"fileName":{"type":"string","nullable":true},"fileSize":{"type":"integer","nullable":true},"appId":{"type":"string","nullable":true,"description":"Owning project (component) id, or null if org-wide."},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","type","deploymentOnly"]},"Integration":{"type":"object","description":"A configured third-party integration. Read-only on /v1. The `summary` map only contains fields on a per-type allowlist — credentials (webhook URLs, API tokens, signing secrets, account emails) are never echoed.","properties":{"type":{"type":"string","enum":["slack","jira","envSync","observability","deployment","vcs","webhooks"]},"displayName":{"type":"string"},"isConfigured":{"type":"boolean","description":"Whether the org has set up this integration at all. False means the config doc does not exist; `summary` will be empty."},"summary":{"type":"object","additionalProperties":true,"description":"Allowlisted, credential-free fields from the integration config. Shape varies by type — see source for the per-type allowlist."}},"required":["type","displayName","isConfigured","summary"]},"Deployment":{"type":"object","description":"A single deployment attempt. Read-only on /v1 — deployments are spawned by GitHub Actions, the deployment wizard, or external CI providers, not by this API.","properties":{"id":{"type":"string"},"appId":{"type":"string","nullable":true},"appName":{"type":"string","nullable":true},"platform":{"type":"string","enum":["android","ios","web","backend"],"nullable":true},"targetId":{"type":"string","nullable":true,"description":"e.g. `play:internal`, `ghenv:staging`."},"targetDisplayName":{"type":"string","nullable":true},"buildVersion":{"type":"string","nullable":true},"versionCode":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","building","deploying","success","failed","cancelled","testsFailed"]},"statusMessage":{"type":"string","nullable":true},"errorMessage":{"type":"string","nullable":true},"githubRunId":{"type":"string","nullable":true},"githubRunUrl":{"type":"string","nullable":true},"triggeredByUid":{"type":"string","nullable":true},"triggeredByName":{"type":"string","nullable":true},"releaseId":{"type":"string","nullable":true},"releaseVersion":{"type":"string","nullable":true},"snapshotId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"startedAt":{"type":"string","format":"date-time","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","status"]},"Issue":{"type":"object","description":"An issue / bug / task / improvement / feature. The /v1 surface exposes the basics every automation tool needs (title / status / assignee / labels / dates) and skips the in-app rich fields (relations, linked PRs, SLA, time tracking, type-specific blobs).","properties":{"id":{"type":"string"},"sequenceNumber":{"type":"integer","nullable":true,"description":"Org-wide sequential issue number assigned by a Firestore trigger after create. May be null on docs that were just created."},"appId":{"type":"string","description":"Owning project (component) id."},"title":{"type":"string"},"description":{"type":"string"},"severity":{"type":"string","enum":["minor","major","critical","blocker"]},"status":{"type":"string","enum":["newBug","triaged","inProgress","blocked","fixed","verified","wontFix","duplicate"]},"statusGroup":{"type":"string","enum":["backlog","active","done","closed"],"description":"Denormalized board column derived server-side from `status`. Read-only — set `status` and the server picks the right group."},"issueType":{"type":"string","enum":["bug","enhancement","feature","task"]},"assignedToUid":{"type":"string","nullable":true},"labels":{"type":"array","items":{"type":"string"}},"dueDate":{"type":"string","format":"date-time","nullable":true},"startDate":{"type":"string","format":"date-time","nullable":true},"estimateMinutes":{"type":"integer","nullable":true},"githubIssueNumber":{"type":"integer","nullable":true},"githubIssueUrl":{"type":"string","nullable":true},"jiraIssueKey":{"type":"string","nullable":true},"jiraIssueUrl":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true},"version":{"type":"integer","description":"Optimistic-concurrency counter, increments on every successful update."}},"required":["id","appId","title","severity","status","statusGroup","issueType","labels","version"]},"IssueInput":{"type":"object","description":"Create body. `appId` and `title` are required; everything else uses sensible defaults.","properties":{"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"severity":{"type":"string","enum":["minor","major","critical","blocker"]},"status":{"type":"string","enum":["newBug","triaged","inProgress","blocked","fixed","verified","wontFix","duplicate"]},"issueType":{"type":"string","enum":["bug","enhancement","feature","task"]},"assignedToUid":{"type":"string","nullable":true},"labels":{"type":"array","items":{"type":"string"}},"dueDate":{"type":"string","format":"date-time","nullable":true},"startDate":{"type":"string","format":"date-time","nullable":true},"estimateMinutes":{"type":"integer","nullable":true}},"required":["appId","title"]},"Runbook":{"type":"object","description":"An operational runbook — markdown content stored alongside org docs but flagged as `isRunbook`.","properties":{"id":{"type":"string"},"title":{"type":"string"},"bodyMd":{"type":"string","description":"Markdown body."},"runbookType":{"type":"string","description":"Free-form classifier — `incident_response`, `deployment`, `rollback`, `maintenance`, etc."},"linkedAppIds":{"type":"array","items":{"type":"string"}},"linkedIncidentSeverities":{"type":"array","items":{"type":"string"},"description":"Severities that auto-surface this runbook during incidents."},"tags":{"type":"array","items":{"type":"string"}},"pinned":{"type":"boolean"},"visibilityRoleMin":{"type":"string"},"generatedByAi":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","title","bodyMd","runbookType","linkedAppIds","tags"]},"RunbookInput":{"type":"object","properties":{"title":{"type":"string"},"bodyMd":{"type":"string"},"runbookType":{"type":"string"},"linkedAppIds":{"type":"array","items":{"type":"string"}},"linkedIncidentSeverities":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"pinned":{"type":"boolean"},"visibilityRoleMin":{"type":"string"}},"required":["title","runbookType"]},"ScorecardRule":{"type":"object","description":"One yes/no check evaluated against an entity. The `type` field discriminates the evaluator.","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["has_owner_team","has_description","lifecycle_in"]},"label":{"type":"string"},"description":{"type":"string","nullable":true},"weight":{"type":"integer","minimum":1,"maximum":10},"params":{"type":"object"}},"required":["id","type","label","weight"]},"ScorecardTier":{"type":"object","properties":{"name":{"type":"string","description":"Lowercase identifier — e.g. bronze / silver / gold."},"minScore":{"type":"integer","minimum":0,"maximum":100}},"required":["name","minScore"]},"Scorecard":{"type":"object","description":"An admin-defined bundle of rules that scores catalog entities and assigns them a tier.","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"applicableKinds":{"type":"array","items":{"type":"string","enum":["component","api","resource","system","domain"]}},"rules":{"type":"array","items":{"$ref":"#/components/schemas/ScorecardRule"}},"tiers":{"type":"array","items":{"$ref":"#/components/schemas/ScorecardTier"}},"tags":{"type":"array","items":{"type":"string"}},"scopeTeamId":{"type":"string","nullable":true,"description":"If set, only grades entities owned by this team."},"scopeTags":{"type":"array","items":{"type":"string"},"description":"If non-empty, only grades entities carrying at least one of these tags."},"scopeSystemId":{"type":"string","nullable":true,"description":"If set, only grades entities belonging to this System."},"scopeDomainId":{"type":"string","nullable":true,"description":"If set, only grades entities belonging to this Domain."},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","applicableKinds","rules","tiers"]},"ScorecardInput":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"applicableKinds":{"type":"array","items":{"type":"string","enum":["component","api","resource","system","domain"]}},"rules":{"type":"array","items":{"$ref":"#/components/schemas/ScorecardRule"}},"tiers":{"type":"array","items":{"$ref":"#/components/schemas/ScorecardTier"}},"tags":{"type":"array","items":{"type":"string"}},"scopeTeamId":{"type":"string","nullable":true,"description":"Optional: only grade entities owned by this team."},"scopeTags":{"type":"array","items":{"type":"string"},"description":"Optional: only grade entities with at least one of these tags."},"scopeSystemId":{"type":"string","nullable":true,"description":"Optional: only grade entities belonging to this System."},"scopeDomainId":{"type":"string","nullable":true,"description":"Optional: only grade entities belonging to this Domain."}},"required":["name","applicableKinds","rules"]},"User":{"type":"object","description":"A user (org member) as a catalog entity. Read-only — write goes through the invite flow.","properties":{"id":{"type":"string","description":"Firebase Auth uid."},"email":{"type":"string","nullable":true},"displayName":{"type":"string","nullable":true},"role":{"type":"string","nullable":true,"description":"Org role — owner / admin / member / viewer."},"isActive":{"type":"boolean"},"avatarKey":{"type":"string","nullable":true},"avatarBgColor":{"type":"string","nullable":true},"avatarFontColor":{"type":"string","nullable":true},"teamIds":{"type":"array","items":{"type":"string"},"description":"Ids of every team the user belongs to."},"lastLoginAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","isActive","teamIds"]},"OnCallBinding":{"type":"object","description":"A binding from a team or component to an on-call provider. Provider credentials live in `_config/oncallIntegration` and are never exposed by /v1.","properties":{"id":{"type":"string"},"scope":{"type":"string","enum":["team","component","resource"]},"targetId":{"type":"string","description":"Team id when scope=team, app id when scope=component."},"provider":{"type":"string","enum":["pagerduty","opsgenie","manual"]},"scheduleId":{"type":"string","nullable":true,"description":"Provider-side schedule id; null for manual bindings."},"label":{"type":"string","nullable":true},"currentlyOnCallUserName":{"type":"string","nullable":true},"currentlyOnCallUserEmail":{"type":"string","nullable":true},"currentlyOnCallUserUid":{"type":"string","nullable":true,"description":"Resolved org employee uid when the on-call email matches."},"currentShiftStartsAt":{"type":"string","format":"date-time","nullable":true},"currentShiftEndsAt":{"type":"string","format":"date-time","nullable":true},"lastFetchedAt":{"type":"string","format":"date-time","nullable":true},"lastFetchError":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","scope","targetId","provider"]},"OnCallBindingInput":{"type":"object","description":"Create payload for an on-call binding. `scheduleId` is required when `provider` is `pagerduty` or `opsgenie`; ignored for `manual`.","properties":{"scope":{"type":"string","enum":["team","component","resource"]},"targetId":{"type":"string"},"provider":{"type":"string","enum":["pagerduty","opsgenie","manual"]},"scheduleId":{"type":"string","nullable":true},"label":{"type":"string","nullable":true}},"required":["scope","targetId","provider"]},"Slo":{"type":"object","description":"A Service Level Objective bound to a single component (project). Error budget fields are server-managed — write-paths only validate type / target / window / unit / dataSource. The sloCalculator function recalculates `errorBudget*` and `status` every 15 minutes.","properties":{"id":{"type":"string"},"name":{"type":"string"},"appId":{"type":"string","description":"Component the SLO applies to."},"type":{"type":"string","enum":["availability","latency","errorRate","throughput","custom"]},"target":{"type":"number","description":"For availability/errorRate: percentage 0-100. For latency: percentile (e.g. 99 for p99). For throughput/custom: caller-defined units."},"unit":{"type":"string","nullable":true},"window":{"type":"string","enum":["rolling7d","rolling30d","rolling90d","calendarMonth","calendarQuarter"]},"currentValue":{"type":"number","nullable":true},"errorBudgetTotal":{"type":"number","nullable":true},"errorBudgetRemaining":{"type":"number","nullable":true},"errorBudgetPercentUsed":{"type":"number","nullable":true},"status":{"type":"string","enum":["met","atRisk","breached"],"nullable":true},"dataSource":{"type":"string","nullable":true},"lastUpdatedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","name","appId","type","target","window"]},"SloInput":{"type":"object","properties":{"name":{"type":"string"},"appId":{"type":"string"},"type":{"type":"string","enum":["availability","latency","errorRate","throughput","custom"]},"target":{"type":"number"},"unit":{"type":"string","nullable":true},"window":{"type":"string","enum":["rolling7d","rolling30d","rolling90d","calendarMonth","calendarQuarter"]},"dataSource":{"type":"string","nullable":true}},"required":["name","appId","type","target","window"]},"ScaffoldParam":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["string","enum","team","boolean"]},"required":{"type":"boolean"},"default":{"type":"string","nullable":true},"helpText":{"type":"string","nullable":true},"options":{"type":"array","items":{"type":"string"},"nullable":true}},"required":["key","label","type"]},"ScaffoldTemplate":{"type":"object","description":"A Backstage-style scaffold template. Points at a GitHub template repo, defines a parameter schema, and optionally creates a matching catalog entity (component / api / resource / system / domain) when scaffolded.","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"templateRepo":{"type":"object","properties":{"owner":{"type":"string","nullable":true},"repo":{"type":"string","nullable":true}}},"targetEntityKind":{"type":"string","enum":["component","api","resource","system","domain"],"nullable":true},"parameters":{"type":"array","items":{"$ref":"#/components/schemas/ScaffoldParam"}},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id"]},"CostRollup":{"type":"object","description":"Per-project cost rollup over the trailing 30 days plus MTD totals. All amounts are in cents (USD by default).","properties":{"appId":{"type":"string"},"mtdCents":{"type":"integer","description":"Spend so far this calendar month."},"last30dCents":{"type":"integer"},"prev30dCents":{"type":"integer"},"byCategory":{"type":"object","description":"Cents by CostCategory over the last 30 days.","additionalProperties":{"type":"integer"}},"byService":{"type":"object","description":"Cents by service string over the last 30 days.","additionalProperties":{"type":"integer"}},"topServices":{"type":"array","description":"Top 5 services by spend (descending).","items":{"type":"object","properties":{"service":{"type":"string"},"cents":{"type":"integer"}}}},"dailySeries":{"type":"array","description":"30 daily totals in cents, oldest-first (index 0 is 29 days ago).","items":{"type":"integer"}},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"}},"required":["appId","mtdCents","last30dCents","prev30dCents"]},"CostEntry":{"type":"object","properties":{"id":{"type":"string"},"appId":{"type":"string","nullable":true},"appName":{"type":"string","nullable":true},"category":{"type":"string","nullable":true},"service":{"type":"string","nullable":true},"amountCents":{"type":"integer"},"currency":{"type":"string","nullable":true},"periodStart":{"type":"string","format":"date-time","nullable":true},"periodEnd":{"type":"string","format":"date-time","nullable":true},"source":{"type":"string","nullable":true,"enum":["auto","manual",null]},"createdAt":{"type":"string","format":"date-time","nullable":true}}},"ErrorTrackerIssue":{"type":"object","description":"One issue (group of similar exceptions) returned by the upstream provider.","properties":{"id":{"type":"string"},"title":{"type":"string"},"level":{"type":"string"},"count24h":{"type":"integer","nullable":true},"lastSeenAt":{"type":"string","format":"date-time","nullable":true},"url":{"type":"string","nullable":true}},"required":["id","title","level"]},"ErrorTrackerSnapshot":{"type":"object","properties":{"provider":{"type":"string","enum":["sentry","rollbar","bugsnag"],"nullable":true},"totalOpen":{"type":"integer","nullable":true},"totalEvents24h":{"type":"integer","nullable":true},"fetchedAt":{"type":"string","format":"date-time","nullable":true},"lastFetchError":{"type":"string","nullable":true},"issues":{"type":"array","items":{"$ref":"#/components/schemas/ErrorTrackerIssue"}}}},"ErrorTracker":{"type":"object","description":"An app's error-tracking integration, including the most recent fetched snapshot. The provider credential is NEVER exposed — only the `vaultKeyword` reference (which is a public-safe id).","properties":{"appId":{"type":"string"},"provider":{"type":"string","enum":["sentry","rollbar","bugsnag"],"nullable":true},"isEnabled":{"type":"boolean"},"sentryOrg":{"type":"string","nullable":true},"sentryProject":{"type":"string","nullable":true},"sentryBaseUrl":{"type":"string","nullable":true},"bugsnagProjectId":{"type":"string","nullable":true},"vaultKeyword":{"type":"string","nullable":true},"configuredAt":{"type":"string","format":"date-time","nullable":true},"snapshot":{"oneOf":[{"$ref":"#/components/schemas/ErrorTrackerSnapshot"},{"type":"null"}]}}},"ErrorTrackerSnapshotSummary":{"type":"object","description":"Summary entry in the historical error-tracker list.","properties":{"id":{"type":"string"},"appId":{"type":"string"},"provider":{"type":"string","nullable":true},"totalOpen":{"type":"integer","nullable":true},"totalEvents24h":{"type":"integer","nullable":true},"fetchedAt":{"type":"string","format":"date-time","nullable":true}}},"DriftSummary":{"type":"object","properties":{"totalMappings":{"type":"integer"},"inSyncCount":{"type":"integer"},"driftedCount":{"type":"integer"},"failedCount":{"type":"integer"},"neverSyncedCount":{"type":"integer"},"staleCount":{"type":"integer"}}},"DriftEntry":{"type":"object","properties":{"mappingId":{"type":"string"},"vaultItemId":{"type":"string","nullable":true},"vaultItemName":{"type":"string","nullable":true},"destination":{"type":"string","nullable":true},"destinationKey":{"type":"string","nullable":true},"environment":{"type":"string","nullable":true},"severity":{"type":"string","enum":["failed","never_synced","stale"]},"lastSyncedAt":{"type":"string","format":"date-time","nullable":true},"lastSyncError":{"type":"string","nullable":true},"ageHours":{"type":"number","nullable":true}},"required":["mappingId","severity"]},"DriftCurrent":{"type":"object","description":"The most recent drift scan for one app.","properties":{"appId":{"type":"string"},"scannedAt":{"type":"string","format":"date-time","nullable":true},"scannedByUid":{"type":"string","nullable":true},"summary":{"$ref":"#/components/schemas/DriftSummary"},"entries":{"type":"array","items":{"$ref":"#/components/schemas/DriftEntry"}}}},"DriftSnapshotSummary":{"type":"object","description":"Summary entry in the historical drift list.","properties":{"id":{"type":"string"},"appId":{"type":"string"},"scannedAt":{"type":"string","format":"date-time","nullable":true},"scannedByUid":{"type":"string","nullable":true},"summary":{"$ref":"#/components/schemas/DriftSummary"}}},"SloSnapshot":{"type":"object","description":"Point-in-time error-budget reading written by the sloCalculator every 15 minutes. Used by the burn-down chart.","properties":{"id":{"type":"string"},"takenAt":{"type":"string","format":"date-time","nullable":true},"currentValue":{"type":"number","nullable":true},"errorBudgetTotal":{"type":"number","nullable":true},"errorBudgetRemaining":{"type":"number","nullable":true},"errorBudgetPercentUsed":{"type":"number","nullable":true},"status":{"type":"string","nullable":true}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}},"security":[{"BearerPAT":[]}],"paths":{"/projects":{"get":{"summary":"List projects","tags":["Projects"],"responses":{"200":{"description":"Project list","content":{"application/json":{"schema":{"type":"object","properties":{"projects":{"type":"array","items":{"$ref":"#/components/schemas/Project"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"summary":"Create project","tags":["Projects"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"githubUrl":{"type":"string","nullable":true}},"required":["name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/projects/{appId}":{"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get project","tags":["Projects"],"responses":{"200":{"description":"Project","content":{"application/json":{"schema":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update project","tags":["Projects"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"ownerTeamId":{"type":"string","nullable":true},"archived":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated project","content":{"application/json":{"schema":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete project","tags":["Projects"],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/teams":{"get":{"summary":"List teams","tags":["Teams"],"responses":{"200":{"description":"Team list","content":{"application/json":{"schema":{"type":"object","properties":{"teams":{"type":"array","items":{"$ref":"#/components/schemas/Team"}}}}}}}}},"post":{"summary":"Create team","tags":["Teams"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"color":{"type":"string","nullable":true},"slackChannel":{"type":"string","nullable":true},"leadUid":{"type":"string","nullable":true},"memberUids":{"type":"array","items":{"type":"string"}}},"required":["name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"team":{"$ref":"#/components/schemas/Team"}}}}}}}}},"/teams/{teamId}":{"parameters":[{"name":"teamId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get team","tags":["Teams"],"responses":{"200":{"description":"Team"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update team","tags":["Teams"],"responses":{"200":{"description":"Updated team"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete team","tags":["Teams"],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/apis":{"get":{"summary":"List APIs in the catalog","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All APIs in the calling token's org","content":{"application/json":{"schema":{"type":"object","properties":{"apis":{"type":"array","items":{"$ref":"#/components/schemas/Api"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"summary":"Create an API","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"api":{"$ref":"#/components/schemas/Api"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/apis/{apiId}":{"parameters":[{"name":"apiId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get an API by id","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested API","content":{"application/json":{"schema":{"type":"object","properties":{"api":{"$ref":"#/components/schemas/Api"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update an API","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"api":{"$ref":"#/components/schemas/Api"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete an API","description":"Requires a Personal Access Token with `admin` scope. Org-scoped API Keys cannot delete.","tags":["Catalog"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/apis/{apiId}/spec":{"parameters":[{"name":"apiId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Fetch the resolved OpenAPI spec for an API entity","description":"Server-side fetch of the API's `specUrl`. GitHub-hosted private specs are authenticated using the org's VCS connection token; public URLs are fetched anonymously.","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"Raw spec text + format hint + size","content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","description":"Raw spec text (JSON or YAML)."},"format":{"type":"string","enum":["json","yaml"]},"sizeBytes":{"type":"integer"}},"required":["content","format"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"502":{"description":"Upstream spec source returned a non-OK response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/resources":{"get":{"summary":"List resources in the catalog","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All resources in the calling token's org","content":{"application/json":{"schema":{"type":"object","properties":{"resources":{"type":"array","items":{"$ref":"#/components/schemas/Resource"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"summary":"Create a resource","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"resource":{"$ref":"#/components/schemas/Resource"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/resources/{resourceId}":{"parameters":[{"name":"resourceId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a resource by id","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested resource","content":{"application/json":{"schema":{"type":"object","properties":{"resource":{"$ref":"#/components/schemas/Resource"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update a resource","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"resource":{"$ref":"#/components/schemas/Resource"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete a resource","description":"Requires a Personal Access Token with `admin` scope. Org-scoped API Keys cannot delete.","tags":["Catalog"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/systems":{"get":{"summary":"List systems","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All systems in the calling token's org","content":{"application/json":{"schema":{"type":"object","properties":{"systems":{"type":"array","items":{"$ref":"#/components/schemas/System"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"summary":"Create a system","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"system":{"$ref":"#/components/schemas/System"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/systems/{systemId}":{"parameters":[{"name":"systemId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a system by id","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested system","content":{"application/json":{"schema":{"type":"object","properties":{"system":{"$ref":"#/components/schemas/System"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update a system","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"system":{"$ref":"#/components/schemas/System"}}}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete a system","description":"Requires a Personal Access Token with `admin` scope. Org-scoped API Keys cannot delete.","tags":["Catalog"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/domains":{"get":{"summary":"List domains","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All domains in the calling token's org","content":{"application/json":{"schema":{"type":"object","properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/Domain"}}}}}}}}},"post":{"summary":"Create a domain","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"$ref":"#/components/schemas/Domain"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/domains/{domainId}":{"parameters":[{"name":"domainId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a domain by id","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested domain","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"$ref":"#/components/schemas/Domain"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update a domain","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"$ref":"#/components/schemas/Domain"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete a domain","description":"Requires a Personal Access Token with `admin` scope.","tags":["Catalog"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/dependencies":{"get":{"summary":"List dependency edges","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All edges in the calling token's org, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"edges":{"type":"array","items":{"$ref":"#/components/schemas/DependencyEdge"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"summary":"Create a dependency edge","description":"Records that `from` depends on `to`. Both endpoints must exist; self-loops and duplicate edges (same triple) are rejected.","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DependencyEdgeInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"edge":{"$ref":"#/components/schemas/DependencyEdge"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"An edge with the same fromKind+fromId+toKind+toId+type already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/dependencies/{edgeId}":{"parameters":[{"name":"edgeId","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"summary":"Delete a dependency edge","description":"Edges are immutable; to change one, delete and re-create. Requires admin scope (PAT only).","tags":["Catalog"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/secrets":{"get":{"summary":"List vault item metadata","description":"Read-only metadata listing. Encrypted values are never returned. Requires admin scope (PAT only) — even secret names are sensitive enough to gate behind a human-issued credential.","tags":["Secrets"],"security":[{"BearerPAT":["admin"]}],"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string"}},{"name":"appId","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Secret metadata sorted by name (case-insensitive)","content":{"application/json":{"schema":{"type":"object","properties":{"secrets":{"type":"array","items":{"$ref":"#/components/schemas/Secret"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/secrets/{secretId}":{"parameters":[{"name":"secretId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a single secret's metadata","description":"Same admin-only access posture as the list endpoint.","tags":["Secrets"],"security":[{"BearerPAT":["admin"]}],"responses":{"200":{"description":"The requested secret's metadata","content":{"application/json":{"schema":{"type":"object","properties":{"secret":{"$ref":"#/components/schemas/Secret"}}}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/integrations":{"get":{"summary":"List configured integrations","description":"Read-only. Returns one entry per known integration type, including the ones the org has not configured (so callers can see the full menu of options + which are wired). Credentials are never echoed.","tags":["Integrations"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All integrations for the calling token's org","content":{"application/json":{"schema":{"type":"object","properties":{"integrations":{"type":"array","items":{"$ref":"#/components/schemas/Integration"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/integrations/{type}":{"parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a single integration by type","description":"Returns the integration entry whether or not the org has configured it (`isConfigured: false` for unconfigured ones).","tags":["Integrations"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested integration","content":{"application/json":{"schema":{"type":"object","properties":{"integration":{"$ref":"#/components/schemas/Integration"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/deployments":{"get":{"summary":"List deployments","description":"Read-only. Returns the most-recent deployments first (capped at 50 by default, max 500). Supports filtering by `appId`, `status`, `platform`, `releaseId`, `triggeredByUid` query params (any combination).","tags":["Deployments"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"appId","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"platform","in":"query","required":false,"schema":{"type":"string"}},{"name":"releaseId","in":"query","required":false,"schema":{"type":"string"}},{"name":"triggeredByUid","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"Deployments matching the filters, newest-first","content":{"application/json":{"schema":{"type":"object","properties":{"deployments":{"type":"array","items":{"$ref":"#/components/schemas/Deployment"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/deployments/{deploymentId}":{"parameters":[{"name":"deploymentId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a deployment by id","tags":["Deployments"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested deployment","content":{"application/json":{"schema":{"type":"object","properties":{"deployment":{"$ref":"#/components/schemas/Deployment"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/issues":{"get":{"summary":"List issues","description":"Returns issues newest-first. Supports filtering by `appId`, `status`, `severity`, `issueType`, `assignedToUid` query params (any combination).","tags":["Issues"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"appId","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"severity","in":"query","required":false,"schema":{"type":"string"}},{"name":"issueType","in":"query","required":false,"schema":{"type":"string"}},{"name":"assignedToUid","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Issues in the calling token's org matching the filters","content":{"application/json":{"schema":{"type":"object","properties":{"issues":{"type":"array","items":{"$ref":"#/components/schemas/Issue"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"summary":"Create an issue","description":"`sequenceNumber` is assigned asynchronously by a Firestore trigger after the doc is written, so the response body's `sequenceNumber` will typically be null on the create call. Re-read the issue (or list) a moment later to see the assigned number.","tags":["Issues"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"$ref":"#/components/schemas/Issue"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/issues/{issueId}":{"parameters":[{"name":"issueId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get an issue by id","tags":["Issues"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested issue","content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"$ref":"#/components/schemas/Issue"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update an issue","description":"Setting `status` recomputes `statusGroup` server-side. The audit log emits a specialized event (ISSUE_STATUS_CHANGED, ISSUE_ASSIGNED, ISSUE_PRIORITY_CHANGED, ISSUE_TYPE_CHANGED) when one of those high-signal fields actually changed.","tags":["Issues"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"$ref":"#/components/schemas/Issue"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Hard-delete an issue","description":"Cascade-deletes the issue's activity subcollection. Requires admin scope (PAT only).","tags":["Issues"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/runbooks":{"get":{"summary":"List runbooks","tags":["Runbooks"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All non-deleted runbooks in the calling token's org","content":{"application/json":{"schema":{"type":"object","properties":{"runbooks":{"type":"array","items":{"$ref":"#/components/schemas/Runbook"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"summary":"Create a runbook","tags":["Runbooks"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunbookInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"runbook":{"$ref":"#/components/schemas/Runbook"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/runbooks/{runbookId}":{"parameters":[{"name":"runbookId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a runbook by id","tags":["Runbooks"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested runbook","content":{"application/json":{"schema":{"type":"object","properties":{"runbook":{"$ref":"#/components/schemas/Runbook"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update a runbook","tags":["Runbooks"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunbookInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"runbook":{"$ref":"#/components/schemas/Runbook"}}}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Soft-delete a runbook","description":"Sets `isDeleted=true` rather than hard-deleting so historical references in incidents and the Activity feed survive. Requires admin scope (PAT only).","tags":["Runbooks"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Soft-deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/oncall/bindings":{"get":{"summary":"List on-call bindings","description":"Lists every on-call binding in the calling token's org. Optional query filters: `scope`, `targetId`, `provider`.","tags":["On-Call"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["team","component","resource"]}},{"name":"targetId","in":"query","required":false,"schema":{"type":"string"}},{"name":"provider","in":"query","required":false,"schema":{"type":"string","enum":["pagerduty","opsgenie","manual"]}}],"responses":{"200":{"description":"List of on-call bindings","content":{"application/json":{"schema":{"type":"object","properties":{"bindings":{"type":"array","items":{"$ref":"#/components/schemas/OnCallBinding"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"summary":"Create an on-call binding","tags":["On-Call"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnCallBindingInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"binding":{"$ref":"#/components/schemas/OnCallBinding"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"description":"A binding for the same (scope, targetId, provider) triple already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/oncall/bindings/{bindingId}":{"parameters":[{"name":"bindingId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get an on-call binding","tags":["On-Call"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested on-call binding","content":{"application/json":{"schema":{"type":"object","properties":{"binding":{"$ref":"#/components/schemas/OnCallBinding"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update an on-call binding's label","description":"Only the `label` field can be updated. Structural fields (scope, targetId, provider, scheduleId) are immutable; change them by deleting and recreating the binding.","tags":["On-Call"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","nullable":true}},"required":["label"]}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"binding":{"$ref":"#/components/schemas/OnCallBinding"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete an on-call binding","description":"Hard-deletes the binding doc. The provider integration credentials are unaffected. Requires admin scope (PAT only).","tags":["On-Call"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/oncall/bindings/{bindingId}/refresh":{"parameters":[{"name":"bindingId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"summary":"Refresh an on-call binding from its upstream provider","description":"Forces a fresh fetch from PagerDuty/Opsgenie and updates the cached on-call user and shift fields. Manual bindings return immediately with cached fields. Returns `502 upstream_unavailable` if the provider call fails — the binding's `lastFetchError` field is updated even on failure so admins can see what broke.","tags":["On-Call"],"security":[{"BearerPAT":["write"]}],"responses":{"200":{"description":"Refreshed binding","content":{"application/json":{"schema":{"type":"object","properties":{"binding":{"$ref":"#/components/schemas/OnCallBinding"}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"502":{"description":"The upstream provider call failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/scaffold-templates":{"get":{"summary":"List scaffold templates","description":"Returns every scaffold template registered in the calling token's org, sorted by name. Templates power the in-app 'New from template' wizard and the equivalent Terraform / CLI scaffolders. Registration and deletion are intentionally not on /v1 — they go through admin callables to keep GitHub repo coords out of declarative IaC.","tags":["ScaffoldTemplates"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"List of scaffold templates","content":{"application/json":{"schema":{"type":"object","properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/ScaffoldTemplate"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/scaffold-templates/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get one scaffold template","tags":["ScaffoldTemplates"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested scaffold template","content":{"application/json":{"schema":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/ScaffoldTemplate"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/costs":{"get":{"summary":"Get the per-project cost rollup","description":"Returns the trailing-30-day cost rollup for one project, including MTD spend, prev-30d for MoM delta, top 5 services, and a 30-bucket daily series for the chart on Project Overview.","tags":["Costs"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Cost rollup","content":{"application/json":{"schema":{"type":"object","properties":{"cost":{"$ref":"#/components/schemas/CostRollup"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/costs/entries":{"get":{"summary":"List recent cost entries (admin scope)","description":"Read-only listing of raw cost rows for forensic / audit purposes. Requires admin scope (PAT only).","tags":["Costs"],"security":[{"BearerPAT":["admin"]}],"parameters":[{"name":"appId","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"Recent cost entries (most recent first)","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/CostEntry"}}}}}}},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/error-tracking":{"get":{"summary":"Get the current error-tracker connector + snapshot for an app","description":"Returns the configured error-tracker (Sentry / Rollbar / Bugsnag) for the given app along with the most recent fetched issue snapshot. Returns `{tracker: null}` if no connector is configured. The provider credential is never exposed — only the `vaultKeyword` reference, which is a public-safe id.","tags":["ErrorTracking"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Connector + snapshot or null","content":{"application/json":{"schema":{"type":"object","properties":{"tracker":{"oneOf":[{"$ref":"#/components/schemas/ErrorTracker"},{"type":"null"}]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/error-tracking/snapshots":{"get":{"summary":"List historical error-tracker snapshots for an app","tags":["ErrorTracking"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"Snapshots in descending fetchedAt order","content":{"application/json":{"schema":{"type":"object","properties":{"snapshots":{"type":"array","items":{"$ref":"#/components/schemas/ErrorTrackerSnapshotSummary"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/drift":{"get":{"summary":"Get the current drift snapshot for an app","description":"Returns the most recent drift scan for the given app, including every drifted env-sync mapping. Returns `{drift: null}` if the app has never been scanned.","tags":["Drift"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Current drift snapshot (or null when the app has never been scanned)","content":{"application/json":{"schema":{"type":"object","properties":{"drift":{"oneOf":[{"$ref":"#/components/schemas/DriftCurrent"},{"type":"null"}]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/drift/snapshots":{"get":{"summary":"List historical drift snapshots for an app","tags":["Drift"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":50}}],"responses":{"200":{"description":"List of snapshots in descending scannedAt order","content":{"application/json":{"schema":{"type":"object","properties":{"snapshots":{"type":"array","items":{"$ref":"#/components/schemas/DriftSnapshotSummary"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/drift/snapshots/{snapshotId}":{"parameters":[{"name":"snapshotId","in":"path","required":true,"schema":{"type":"string"}},{"name":"appId","in":"query","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get one historical drift snapshot","tags":["Drift"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested drift snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"snapshot":{"$ref":"#/components/schemas/DriftCurrent"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/slos":{"get":{"summary":"List SLOs","description":"Lists every SLO in the calling token's org. Optional query filters: `appId`, `status`, `type`.","tags":["SLOs"],"security":[{"BearerPAT":["read"]}],"parameters":[{"name":"appId","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["met","atRisk","breached"]}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["availability","latency","errorRate","throughput","custom"]}}],"responses":{"200":{"description":"List of SLOs","content":{"application/json":{"schema":{"type":"object","properties":{"slos":{"type":"array","items":{"$ref":"#/components/schemas/Slo"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"summary":"Create an SLO","tags":["SLOs"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SloInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"slo":{"$ref":"#/components/schemas/Slo"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/slos/{sloId}":{"parameters":[{"name":"sloId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get an SLO","tags":["SLOs"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested SLO","content":{"application/json":{"schema":{"type":"object","properties":{"slo":{"$ref":"#/components/schemas/Slo"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update an SLO","description":"Mutable fields: `name`, `target`, `type`, `window`, `unit`, `dataSource`, `currentValue`. Changing `type`, `target`, or `window` resets the error budget — the sloCalculator will refine the next recalculation.","tags":["SLOs"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SloInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"slo":{"$ref":"#/components/schemas/Slo"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete an SLO","description":"Cascade-deletes the SLO's snapshot history. Requires admin scope (PAT only).","tags":["SLOs"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/slos/{sloId}/snapshots":{"parameters":[{"name":"sloId","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":2000,"default":500}}],"get":{"summary":"Get an SLO's burn-down history","description":"Returns up to `limit` snapshots in ascending takenAt order. The sloCalculator writes one snapshot per SLO every 15 minutes, so the default 500-snapshot limit covers ~5 days of history. Use this to power a burn-down chart in your dashboard.","tags":["SLOs"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"List of snapshots","content":{"application/json":{"schema":{"type":"object","properties":{"snapshots":{"type":"array","items":{"$ref":"#/components/schemas/SloSnapshot"}}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/scorecards":{"get":{"summary":"List scorecards","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All scorecards in the calling token's org","content":{"application/json":{"schema":{"type":"object","properties":{"scorecards":{"type":"array","items":{"$ref":"#/components/schemas/Scorecard"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"summary":"Create a scorecard","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScorecardInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"scorecard":{"$ref":"#/components/schemas/Scorecard"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/scorecards/{scorecardId}":{"parameters":[{"name":"scorecardId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a scorecard","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested scorecard","content":{"application/json":{"schema":{"type":"object","properties":{"scorecard":{"$ref":"#/components/schemas/Scorecard"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Update a scorecard","tags":["Catalog"],"security":[{"BearerPAT":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScorecardInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"scorecard":{"$ref":"#/components/schemas/Scorecard"}}}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Delete a scorecard","description":"Cascade-deletes the cached scores for this scorecard. Requires admin scope (PAT only).","tags":["Catalog"],"security":[{"BearerPAT":["admin"]}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/users":{"get":{"summary":"List users (org members)","description":"Read-only. Returns every employee in the calling token's org plus the list of team ids each one belongs to.","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"All users in the calling token's org","content":{"application/json":{"schema":{"type":"object","properties":{"users":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/users/{uid}":{"parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Get a user by uid","tags":["Catalog"],"security":[{"BearerPAT":["read"]}],"responses":{"200":{"description":"The requested user","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/openapi.json":{"get":{"summary":"OpenAPI 3 spec for this API","tags":["Meta"],"security":[],"responses":{"200":{"description":"OpenAPI 3 document","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"x-error-responses":{"Unauthorized":{"description":"The token is missing, malformed, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is valid but doesn't carry the scope this endpoint requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"The resource doesn't exist in the calling token's organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadRequest":{"description":"Required fields missing or input validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}