openapi: 3.1.0 info: contact: email: felixtj.dietrich@tum.de name: Felix T.J. Dietrich description: |- API documentation for the Hephaestus application server. ### Money and exact decimals Every monetary amount and per-unit rate is a JSON number carrying `format: decimal`. It is an exact decimal on the server (`BigDecimal`, backed by a `NUMERIC` column) and MUST NOT be parsed into a binary floating-point type in a language that has an exact decimal one: bind it to `BigDecimal` / `decimal` / `Decimal`, not to `double`. JavaScript has no exact decimal type, so the generated TypeScript client necessarily binds these to `number` (IEEE-754 binary64). That is lossless for every value this API produces, and the margin is large: a binary64 round-trips any decimal of at most 15 significant digits exactly (`DBL_DIG`). Amounts are quantised to 6 decimal places, so they are exact below **$1,000,000,000**; per-1M-token rates are quantised to 8 places, so they are exact below **$10,000,000** per 1M tokens; budget caps are quantised to 2 places and their column tops out at $99,999,999.99. Every reachable value sits orders of magnitude inside those bounds. What that margin does NOT license is arithmetic. Totals, remaining budget and cap verdicts are computed on the server in exact decimal and shipped as fields; a client that re-derives them by summing rows is accumulating binary rounding error the server does not have. Read the totals, do not add them up. Amounts are USD throughout — the ledger, the caps and the gates all meter in USD, and the currency is therefore part of the field name (`...Usd`) rather than a per-amount field. Where a response also carries `FxRateInfo`, that is a display-only estimate in a second currency and is never an input to a budget decision. license: name: MIT License url: https://github.com/hephaestus-build/Hephaestus/blob/main/LICENSE title: Hephaestus API version: 0.0.0-development servers: - description: Default Server URL url: / security: - bearerAuth: [] tags: - description: The current developer's practice profile name: Practice Profile - description: The authenticated developer's feedback name: Practice feedback - description: Per-workspace LLM spend rollup and budget status name: LLM Usage - description: Practice group trends and review runs for the current developer name: Practice Group Detail - description: Workspace-scoped mentor chat threads name: Mentor Threads - description: Running release identity and update checks name: Instance Release - description: The current developer's standing in each practice name: Practice Standings - description: Recipient responses to delivered practice feedback name: Feedback Response - description: Heph conversations and the sandbox they run in name: Mentor Chat - description: "User account management (settings, deletion)" name: Account - description: Instance-admin account management name: Admin - description: Current user's Slack privacy preferences name: Slack User Preferences - description: "How the workspace's developers split, the reader marked" name: Practices Across The Workspace - description: Per-workspace Outline collection mirroring control plane name: Outline collections - description: The starting catalog copied into new workspaces name: Admin Practice Catalog - description: Why each practice did or did not run on one piece of work. Any workspace member can read it. name: Practice review trace - description: Instance-wide operator settings name: Instance Settings - description: Session lifecycle name: Auth - description: Current instance definitions visible to workspace administrators name: Practice Catalog - description: Workspace-scoped practice-review policy name: Practice Review Settings - description: Instance-admin-only read-only access to users name: User view - description: Workspace integration connection management name: Connections - description: Up/down votes on mentor assistant messages name: Mentor Votes - description: "Workspace-admin access to review runs, observations, and feedback\ \ delivery history" name: Practice reviews - description: GDPR Art. 20 self-service data export name: Account - description: Instance-administrator access and erasure requests name: Person Data - description: Workspace-scoped history of admin configuration changes name: Config Audit - description: |- Vendor OAuth redirect ingress at /oauth/callback/{kind}. Unauthenticated — identity comes from the HMAC-signed state param. Browsers get 302 redirects on both success and failure; only Accept: application/json requests get 4xx JSON. name: o-auth-callback-controller - description: Recurring reviews of recent work name: Practice Review Sweep - description: Redacted production configuration facts name: Configuration Readiness - description: Identity provider discovery (public) name: Auth discovery - description: Global contributor information name: Contributors - description: User preferences name: Account - description: Instance-admin login provider management name: Admin - description: Per-workspace Slack channel consent + activation name: Slack channel activation - description: "Sign-in, refresh and sign-out for installed clients" name: Client session - description: |- Workspace registry endpoints under /workspaces that operate outside of a specific workspace slug; slugged routes live in {@link WorkspaceController WorkspaceController} via @WorkspaceScopedController. name: workspace-registry-controller - description: Bounded campaigns that review work which already existed name: Practice Review Backfill - description: Workspace-scoped per-purpose agent configuration name: Agents - description: Workspace-scoped agent job monitoring name: Agent Jobs - description: The current developer's standing in each practice group name: Practice Group Standings - description: Asking for a review of a piece of work by hand name: Practice review requests - description: Current account transparency and research consent name: Consent - description: Read-only access to practice evaluation observations name: Practice Observations - description: Adopt instance catalog practices into a workspace name: Practice Catalog Adoption - description: Team management within workspace name: Teams - description: The developer's own prepared practice feedback name: In-App Feedback - description: Instance-wide email transport verification name: Instance Email - description: "Workspace-scoped \"bring your own\" AI provider connections, models\ \ and settings" name: Workspace LLM - description: Active sessions name: Account - description: |- GitLab-specific REST endpoints used during the workspace creation wizard. Gated on the GITLAB_WORKSPACE_CREATION feature flag. name: git-lab-preflight-controller - description: Review catalogue changes before they affect a workspace name: Practice Catalog - description: Instance-admin LLM connection and settings management name: Admin LLM - description: Manage practice groups name: Practice Groups - description: Public JWK set for verifying Hephaestus session JWTs name: Auth discovery - description: Manage practice definitions name: Practice Catalog - description: Workspace-scoped team settings management name: Team Settings - description: Repository contributions and open work name: Activity - description: Integration sync observability and manual controls name: Sync - description: "Current user identity, linked accounts, deletion" name: Account paths: /.well-known/jwks.json: get: operationId: getJwks responses: "200": content: application/json: schema: type: object additionalProperties: {} description: OK summary: JWK set (public keys only) tags: - Auth discovery /admin/audit: get: operationId: adminListAuthEvents parameters: - in: query name: page required: false schema: type: integer format: int32 default: 0 - in: query name: size required: false schema: type: integer format: int32 default: 50 - in: query name: accountId required: false schema: type: integer format: int64 - in: query name: actingAccountId required: false schema: type: integer format: int64 - in: query name: eventType required: false schema: type: array items: type: string enum: - USER_VIEW - LOGIN - LOGIN_FAILED - LOGOUT - TOKEN_REFRESH - JWT_REVOKED - IDENTITY_LINKED - IDENTITY_UNLINKED - IMPERSONATION_BEGIN - IMPERSONATION_END - ACCOUNT_DELETED - EXPORT_REQUESTED - PERSON_DATA_PREVIEWED - PERSON_DATA_EXPORTED - PERSON_DATA_ERASURE_REQUESTED - APP_ROLE_CHANGED - RESEARCH_CONSENT_REVOKED - WORKSPACE_ELEVATION - LLM_CONNECTION_CREATED - LLM_CONNECTION_UPDATED - LLM_CONNECTION_DELETED - LLM_MODEL_CREATED - LLM_MODEL_UPDATED - LLM_MODEL_DELETED - LLM_MODEL_PRICE_CHANGED - LLM_MODEL_SHARING_CHANGED - LLM_SETTINGS_CHANGED - LOGIN_PROVIDER_CREATED - LOGIN_PROVIDER_UPDATED - LOGIN_PROVIDER_DELETED - SILENT_MODE_CHANGED - PUBLIC_ACTIVITY_CHANGED - in: query name: result required: false schema: type: array items: type: string enum: - SUCCESS - FAILURE - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time responses: "200": content: application/json: schema: $ref: "#/components/schemas/PageResponseDTOAuthEventView" description: OK summary: "List auth audit events (paged, newest first)" tags: - Admin /admin/audit/export: get: operationId: adminExportAuthEvents parameters: - in: query name: accountId required: false schema: type: integer format: int64 - in: query name: actingAccountId required: false schema: type: integer format: int64 - in: query name: eventType required: false schema: type: array items: type: string enum: - USER_VIEW - LOGIN - LOGIN_FAILED - LOGOUT - TOKEN_REFRESH - JWT_REVOKED - IDENTITY_LINKED - IDENTITY_UNLINKED - IMPERSONATION_BEGIN - IMPERSONATION_END - ACCOUNT_DELETED - EXPORT_REQUESTED - PERSON_DATA_PREVIEWED - PERSON_DATA_EXPORTED - PERSON_DATA_ERASURE_REQUESTED - APP_ROLE_CHANGED - RESEARCH_CONSENT_REVOKED - WORKSPACE_ELEVATION - LLM_CONNECTION_CREATED - LLM_CONNECTION_UPDATED - LLM_CONNECTION_DELETED - LLM_MODEL_CREATED - LLM_MODEL_UPDATED - LLM_MODEL_DELETED - LLM_MODEL_PRICE_CHANGED - LLM_MODEL_SHARING_CHANGED - LLM_SETTINGS_CHANGED - LOGIN_PROVIDER_CREATED - LOGIN_PROVIDER_UPDATED - LOGIN_PROVIDER_DELETED - SILENT_MODE_CHANGED - PUBLIC_ACTIVITY_CHANGED - in: query name: result required: false schema: type: array items: type: string enum: - SUCCESS - FAILURE - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time responses: "200": content: text/csv: schema: type: string description: OK summary: "Export the filtered audit log as CSV (newest first, capped)" tags: - Admin /admin/config-audit: get: operationId: adminListConfigAuditEvents parameters: - in: query name: workspaceId required: false schema: type: integer format: int64 - in: query name: page required: false schema: type: integer format: int32 default: 0 - in: query name: size required: false schema: type: integer format: int32 default: 50 - in: query name: entityType required: false schema: type: array items: type: string enum: - PRACTICE_REVIEW_SETTINGS - AGENT_BINDING - AGENT_CONFIG - AI_CONFIG_BINDING - WORKSPACE_ROLE - ACTIVITY_AUTOMATION - WORKSPACE_FEATURES - WORKSPACE_STATUS - WORKSPACE_TOKEN - WORKSPACE_VISIBILITY - PRACTICE_ACTIVE - PRACTICE_USAGE - PRACTICE_DEFINITION - PRACTICE_GROUP - CURATED_PRACTICE - CURATED_PRACTICE_GROUP - WORKSPACE_INSTANCE_LLM_BUDGET - WORKSPACE_OWN_PROVIDER_LLM_BUDGET - WORKSPACE_LLM_BUDGET - WORKSPACE_BYO_LLM_BUDGET - REVIEW_BACKFILL_RUN - REVIEW_SWEEP_SCHEDULE - WORKSPACE_LLM_CONNECTION - WORKSPACE_LLM_MODEL - in: query name: entityId required: false schema: type: string - in: query name: changedKey required: false schema: type: string - in: query name: action required: false schema: type: array items: type: string enum: - CREATED - UPDATED - DELETED - in: query name: actorId required: false schema: type: integer format: int64 - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time responses: "200": content: application/json: schema: $ref: "#/components/schemas/PageResponseDTOConfigAuditEntryView" description: OK summary: "List admin configuration changes across workspaces (paged, newest\ \ first)" tags: - Admin /admin/configuration-readiness: get: operationId: adminGetConfigurationReadiness responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/ConfigurationFact" description: OK summary: Get redacted configuration readiness tags: - Configuration Readiness /admin/email/test: post: description: "Sends a test email through the configured relay to the given address,\ \ or to the caller's verified address when none is given." operationId: adminSendTestEmail requestBody: content: application/json: schema: $ref: "#/components/schemas/EmailTestRequest" responses: "200": content: application/json: schema: $ref: "#/components/schemas/EmailTestResponse" description: Email delivery outcome "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Malformed request or invalid recipient address summary: Send a test email tags: - Instance Email /admin/llm/connections: get: operationId: adminListLlmConnections responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/LlmConnection" description: OK summary: List LLM connections tags: - Admin LLM post: operationId: adminCreateLlmConnection requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateLlmConnectionRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/LlmConnection" description: Connection created; URL in the Location header "409": description: An LLM connection with this slug already exists summary: Create an LLM connection tags: - Admin LLM /admin/llm/connections/probe: post: operationId: adminProbeLlmConnectionDraft requestBody: content: application/json: schema: $ref: "#/components/schemas/ProbeLlmConnectionRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/LlmProbeResult" description: OK summary: Test a draft connection and fetch its models tags: - Admin LLM /admin/llm/connections/{connectionId}/models: post: operationId: adminCreateLlmModel parameters: - in: path name: connectionId required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateLlmModelRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/LlmModel" description: Model created; URL in the Location header "404": description: LLM connection not found "409": description: A model with this slug or upstream model id already exists on the connection summary: Create a model on an LLM connection tags: - Admin LLM /admin/llm/connections/{id}: delete: operationId: adminDeleteLlmConnection parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "204": description: Connection deleted "404": description: LLM connection not found "409": description: Cannot delete a connection still referenced by one or more models summary: Delete an LLM connection tags: - Admin LLM get: operationId: adminGetLlmConnection parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/LlmConnection" description: OK "404": description: LLM connection not found summary: Get an LLM connection tags: - Admin LLM patch: operationId: adminUpdateLlmConnection parameters: - in: path name: id required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateLlmConnectionRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/LlmConnection" description: OK "404": description: LLM connection not found summary: Update an LLM connection tags: - Admin LLM /admin/llm/connections/{id}/probe: post: operationId: adminProbeLlmConnection parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/LlmProbeResult" description: OK summary: Test a stored connection and fetch its models tags: - Admin LLM /admin/llm/models: get: operationId: adminListLlmModels responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/LlmModel" description: OK summary: List LLM catalog models tags: - Admin LLM /admin/llm/models/{id}: delete: operationId: adminDeleteLlmModel parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "204": description: Model deleted "404": description: LLM model not found "409": description: Cannot delete a model still bound to an agent configuration summary: Delete an LLM catalog model tags: - Admin LLM get: operationId: adminGetLlmModel parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/LlmModel" description: OK "404": description: LLM model not found summary: Get an LLM catalog model tags: - Admin LLM patch: operationId: adminUpdateLlmModel parameters: - in: path name: id required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateLlmModelRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/LlmModel" description: OK "404": description: LLM model not found "409": description: Another model on the connection already uses this upstream model id summary: Update a model's metadata tags: - Admin LLM /admin/llm/models/{id}/price: put: operationId: adminUpdateLlmModelPrice parameters: - in: path name: id required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateLlmModelPriceRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/LlmModel" description: OK "404": description: LLM model not found summary: Reprice a model tags: - Admin LLM /admin/llm/models/{id}/sharing: put: operationId: adminUpdateLlmModelSharing parameters: - in: path name: id required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateLlmModelSharingRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/LlmModel" description: OK "404": description: LLM model not found summary: Share a model with all or selected workspaces tags: - Admin LLM /admin/llm/settings: get: operationId: adminGetLlmSettings responses: "200": content: application/json: schema: $ref: "#/components/schemas/InstanceLlmSettings" description: OK summary: Get instance-wide LLM governance settings tags: - Admin LLM put: operationId: adminUpdateLlmSettings requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateInstanceLlmSettingsRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/InstanceLlmSettings" description: OK summary: Update instance-wide LLM governance settings tags: - Admin LLM /admin/llm/usage: get: operationId: adminGetLlmUsageReport parameters: - in: query name: month required: false schema: type: string pattern: "\\d{4}-(0[1-9]|1[0-2])" responses: "200": content: application/json: schema: $ref: "#/components/schemas/AdminLlmUsageReport" description: OK summary: Per-workspace LLM spend rollup for one month (all workspaces) tags: - Admin /admin/login-providers: get: operationId: adminListLoginProviders responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/LoginProviderView" description: OK summary: List login providers tags: - Admin post: operationId: adminCreateLoginProvider requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateLoginProviderRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/LoginProviderView" description: Login provider created; URL in the Location header summary: Create a login provider tags: - Admin /admin/login-providers/{registrationId}: delete: operationId: adminDeleteLoginProvider parameters: - in: path name: registrationId required: true schema: type: string responses: "200": description: OK summary: Delete a login provider tags: - Admin patch: operationId: adminUpdateLoginProvider parameters: - in: path name: registrationId required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateLoginProviderRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/LoginProviderView" description: OK summary: Update a login provider tags: - Admin /admin/person-data/preview: post: operationId: adminPreviewPersonData requestBody: content: application/json: schema: $ref: "#/components/schemas/PreviewRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PersonDataRequest" description: OK summary: Resolve exact identities and preview every personal-data store tags: - Person Data /admin/person-data/providers: get: operationId: adminListPersonDataProviders responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/PersonDataProvider" description: OK summary: List exact provider instances without credentials tags: - Person Data /admin/person-data/{id}: get: operationId: adminGetPersonDataRequest parameters: - in: path name: id required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/PersonDataRequest" description: OK summary: Get a person-data preview or erasure receipt tags: - Person Data /admin/person-data/{id}/erase: post: operationId: adminErasePersonData parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/ErasureRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PersonDataRequest" description: OK summary: Start or resume the preview's audited erasure job tags: - Person Data /admin/person-data/{id}/export: post: operationId: adminExportPersonData parameters: - in: path name: id required: true schema: type: string format: uuid responses: "200": content: application/json: schema: type: string format: binary description: JSON file summary: Download the preview's frozen scope as one JSON file tags: - Person Data /admin/practice-catalog: get: description: "Practice summaries, complete groups, ordering, and catalog state.\ \ Fetch a practice for its full definition." operationId: adminGetCuratedCatalog responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedCatalog" description: OK summary: Read the instance catalog tags: - Admin Practice Catalog /admin/practice-catalog/definition-options: get: description: "Returns available review events, recommended requirements, and\ \ allowed evidence sources by work type" operationId: adminGetPracticeDefinitionOptions responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeDefinitionOptions" description: OK summary: Read practice definition options tags: - Admin Practice Catalog /admin/practice-catalog/groups: post: operationId: adminCreateCuratedGroup requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateCuratedGroupRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/CuratedGroup" description: Group added "409": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Slug already exists summary: Add a group to the catalog tags: - Admin Practice Catalog /admin/practice-catalog/groups/reorder: patch: operationId: adminReorderCuratedGroups parameters: - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/ReorderPracticeGroupsRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedCatalog" description: OK summary: Reorder catalog groups tags: - Admin Practice Catalog /admin/practice-catalog/groups/{slug}: get: operationId: adminGetCuratedGroup parameters: - in: path name: slug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedGroup" description: The group summary: Read a catalog group tags: - Admin Practice Catalog put: operationId: adminUpdateCuratedGroup parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/CuratedGroupRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedGroup" description: The group "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: Replace a group definition tags: - Admin Practice Catalog /admin/practice-catalog/groups/{slug}/override: delete: operationId: adminDeleteCuratedGroupOverride parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedGroup" description: The group "409": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Hephaestus ships no definition for this slug "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: Use the Hephaestus definition of a group tags: - Admin Practice Catalog /admin/practice-catalog/groups/{slug}/override/acknowledgement: put: operationId: adminKeepCuratedGroup parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedGroup" description: The group "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: Keep the saved group customization tags: - Admin Practice Catalog /admin/practice-catalog/groups/{slug}/status: patch: description: Excluding a group also excludes its practices from new workspaces; existing workspaces do not change. operationId: adminUpdateCuratedGroupStatus parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateCuratedStatusRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedCatalog" description: The updated catalog "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: "Exclude a group from new workspaces, or include it again" tags: - Admin Practice Catalog /admin/practice-catalog/order: delete: operationId: adminResetCuratedCatalogOrder parameters: - in: header name: If-Match required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedCatalog" description: OK summary: Use the Hephaestus default order tags: - Admin Practice Catalog /admin/practice-catalog/practices: post: operationId: adminCreateCuratedPractice requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateCuratedPracticeRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: Practice added "409": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Slug already exists summary: Add a practice to the catalog tags: - Admin Practice Catalog /admin/practice-catalog/practices/reorder: patch: operationId: adminReorderCuratedPractices parameters: - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/ReorderPracticesRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedCatalog" description: OK summary: Reorder practices within one catalog group tags: - Admin Practice Catalog /admin/practice-catalog/practices/{slug}: get: operationId: adminGetCuratedPractice parameters: - in: path name: slug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: The practice summary: Read a catalog practice tags: - Admin Practice Catalog put: operationId: adminUpdateCuratedPractice parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/CuratedPracticeRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: The practice "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: Replace a practice definition tags: - Admin Practice Catalog /admin/practice-catalog/practices/{slug}/override: delete: description: "Discards the customization, so the practice follows the Hephaestus\ \ default again." operationId: adminDeleteCuratedPracticeOverride parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: The practice "409": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Hephaestus ships no definition for this slug "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: Use the Hephaestus definition of a practice tags: - Admin Practice Catalog /admin/practice-catalog/practices/{slug}/override/acknowledgement: put: description: Acknowledges that a saved custom practice is no longer shipped. Changed bundled practices use the release endpoint. operationId: adminKeepCuratedPractice parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: The practice "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: Keep the saved practice customization tags: - Admin Practice Catalog /admin/practice-catalog/practices/{slug}/placement: patch: operationId: adminPlaceCuratedPractice parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/PlacePracticeRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedCatalog" description: OK summary: Move a practice to another catalog group tags: - Admin Practice Catalog /admin/practice-catalog/practices/{slug}/release: delete: operationId: adminDeclinePracticeRelease parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: OK summary: Decline this bundled practice update tags: - Admin Practice Catalog get: operationId: adminGetPracticeRelease parameters: - in: path name: slug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeReleaseProposal" description: OK summary: Compare a bundled practice update with the instance version tags: - Admin Practice Catalog put: operationId: adminAcceptPracticeRelease parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/AcceptPracticeReleaseRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: OK summary: Accept selected fields from a bundled practice update tags: - Admin Practice Catalog /admin/practice-catalog/practices/{slug}/status: patch: operationId: adminUpdateCuratedPracticeStatus parameters: - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateCuratedStatusRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: The practice "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: "Exclude a practice from new workspaces, or include it again" tags: - Admin Practice Catalog /admin/product-feedback: get: operationId: adminListProductFeedback parameters: - in: query name: status required: false schema: type: string default: OPEN enum: - OPEN - RESOLVED - ALL - description: Zero-based page index (0..N) in: query name: page required: false schema: type: integer default: 0 minimum: 0 - description: The size of the page to be returned in: query name: size required: false schema: type: integer default: 50 minimum: 1 - description: "Sorting criteria in the format: property,(asc|desc). Default\ \ sort order is ascending. Multiple sort criteria are supported." in: query name: sort required: false schema: type: array items: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PagedModelFeedbackItem" description: OK summary: "List product feedback, newest first" tags: - feedback-admin /admin/product-feedback/surveys: get: operationId: adminListProductSurveys parameters: - description: Zero-based page index (0..N) in: query name: page required: false schema: type: integer default: 0 minimum: 0 - description: The size of the page to be returned in: query name: size required: false schema: type: integer default: 50 minimum: 1 - description: "Sorting criteria in the format: property,(asc|desc). Default\ \ sort order is ascending. Multiple sort criteria are supported." in: query name: sort required: false schema: type: array default: - "createdAt,DESC" items: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PagedModelSurvey" description: OK summary: List product surveys with participation counts tags: - survey-admin post: operationId: adminCreateProductSurvey requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateSurvey" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Survey" description: OK summary: Publish a product survey tags: - survey-admin /admin/product-feedback/surveys/{surveyId}: delete: operationId: adminDeleteProductSurvey parameters: - in: path name: surveyId required: true schema: type: string format: uuid responses: "200": description: OK summary: Delete a survey and every response to it tags: - survey-admin get: operationId: adminGetProductSurvey parameters: - in: path name: surveyId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/Survey" description: OK summary: Read one product survey tags: - survey-admin put: operationId: adminUpdateProductSurvey parameters: - in: path name: surveyId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/SurveyEdit" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Survey" description: OK summary: "Edit a survey's title, purpose, schedule or pause state" tags: - survey-admin /admin/product-feedback/surveys/{surveyId}/email-invitations: get: operationId: adminPreviewSurveyEmailInvitations parameters: - in: path name: surveyId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/SurveyEmailInvitationSummary" description: OK summary: Preview eligible survey email recipients and relay acceptance counts tags: - survey-admin post: operationId: adminSendSurveyEmailInvitations parameters: - in: path name: surveyId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/SurveyEmailInvitationRequest" responses: "200": content: application/json: schema: $ref: "#/components/schemas/SurveyEmailInvitationSummary" description: Invitation request summary "503": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Email delivery is not configured; no invitations were requested summary: Queue up to 1000 new or explicitly retried cancelled survey email invitations tags: - survey-admin /admin/product-feedback/surveys/{surveyId}/responses: get: operationId: adminListProductSurveyResponses parameters: - in: path name: surveyId required: true schema: type: string format: uuid - description: Zero-based page index (0..N) in: query name: page required: false schema: type: integer default: 0 minimum: 0 - description: The size of the page to be returned in: query name: size required: false schema: type: integer default: 50 minimum: 1 - description: "Sorting criteria in the format: property,(asc|desc). Default\ \ sort order is ascending. Multiple sort criteria are supported." in: query name: sort required: false schema: type: array items: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PagedModelSurveyResponse" description: OK summary: "List responses and declines, newest first" tags: - survey-admin /admin/product-feedback/surveys/{surveyId}/responses/export: get: operationId: adminExportProductSurveyResponses parameters: - in: path name: surveyId required: true schema: type: string format: uuid responses: "200": content: text/csv: schema: type: string description: OK summary: Export responses and declines as CSV tags: - survey-admin /admin/product-feedback/surveys/{surveyId}/summary: get: operationId: adminGetProductSurveySummary parameters: - in: path name: surveyId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/SurveySummary" description: OK summary: Aggregate the responses per question tags: - survey-admin /admin/product-feedback/{feedbackId}: patch: operationId: adminTriageProductFeedback parameters: - in: path name: feedbackId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/FeedbackTriage" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/FeedbackItem" description: OK summary: Mark product feedback as resolved or reopen it tags: - feedback-admin /admin/release: get: operationId: adminGetRelease responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReleaseStatus" description: OK summary: Get the running release and the last update check tags: - Instance Release /admin/release/checks: post: operationId: adminCheckRelease responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReleaseStatus" description: OK summary: Check GitHub for a newer release now tags: - Instance Release /admin/settings: get: operationId: adminGetInstanceSettings responses: "200": content: application/json: schema: $ref: "#/components/schemas/InstanceSettings" description: OK summary: Get instance settings tags: - Instance Settings /admin/settings/public-activity: get: operationId: getPublicActivityPolicy responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityPolicy" description: OK summary: Get the instance public activity policy tags: - public-activity-settings put: operationId: updatePublicActivityPolicy requestBody: content: application/json: schema: $ref: "#/components/schemas/PublicActivityPolicy" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityPolicy" description: OK summary: Allow or stop public activity pages tags: - public-activity-settings /admin/settings/silent-mode: patch: operationId: adminUpdateSilentMode parameters: - description: Current settings ETag; required when releasing Silent Mode in: header name: If-Match required: false schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateSilentModeRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/InstanceSettings" description: Silent Mode updated "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required when releasing Silent Mode summary: Engage or release the instance-wide silent mode tags: - Instance Settings /admin/users: get: operationId: adminListUsers parameters: - in: query name: page required: false schema: type: integer format: int32 default: 0 - in: query name: size required: false schema: type: integer format: int32 default: 50 responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/AdminAccountView" description: OK summary: List accounts (paged) tags: - Admin /admin/users/{id}: patch: operationId: adminUpdateUser parameters: - in: path name: id required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateAccountRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/AdminAccountView" description: OK summary: Update an account's app role tags: - Admin /admin/users/{id}/sessions: delete: operationId: adminRevokeUserSessions parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/RevokeSessionsResult" description: OK summary: "Force sign-out: revoke all of an account's active sessions" tags: - Admin /admin/workspaces: get: operationId: adminListWorkspaces responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/AdminWorkspaceView" description: OK summary: List all workspaces (metadata only) tags: - Admin /admin/workspaces/{workspaceSlug}/llm/budget: put: operationId: adminUpdateWorkspaceLlmBudget parameters: - in: path name: workspaceSlug required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateLlmBudgetRequest" required: true responses: "204": description: Cap updated summary: Set or clear a workspace's monthly cap on host-funded LLM spend tags: - Admin /auth/client/configuration: get: description: Public. A client that finds no such endpoint is talking to a server without installed-client sign-in. operationId: getClientSignInConfiguration parameters: - in: query name: clientId required: true schema: type: string pattern: "^[a-p]{32}$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/ClientSignInConfiguration" description: Whether the client is registered "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The client id is not a Chrome extension id summary: Whether this instance lets the given installed client sign in tags: - Client session /auth/client/logout: post: operationId: logoutClientSession requestBody: content: application/json: schema: $ref: "#/components/schemas/ClientRefreshRequest" required: true responses: "204": description: "Signed out, or the secret was already unknown" "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "The body is malformed, or a request with a valid CSRF token\ \ also carries the browser session cookie" "403": content: application/json: {} description: The request carries the browser session cookie without a valid CSRF token. The server refuses it before the endpoint runs. "429": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "This address sent too many installed-client requests. Wait\ \ the number of seconds in the Retry-After header, then try again." summary: End the session its refresh secret belongs to tags: - Client session /auth/client/refresh: post: operationId: refreshClientSession requestBody: content: application/json: schema: $ref: "#/components/schemas/ClientRefreshRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ClientSessionTokens" description: Rotated "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "The body is malformed, or a request with a valid CSRF token\ \ also carries the browser session cookie" "401": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The session has ended. Sign in again. "403": content: application/json: {} description: The request carries the browser session cookie without a valid CSRF token. The server refuses it before the endpoint runs. "429": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "This address sent too many installed-client requests. Wait\ \ the number of seconds in the Retry-After header, then try again." summary: Rotate the session's access token and refresh secret tags: - Client session /auth/client/token: post: operationId: exchangeClientSignIn requestBody: content: application/json: schema: $ref: "#/components/schemas/ClientTokenRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ClientSessionTokens" description: Signed in "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "The body is malformed, the code is unknown, expired, used,\ \ or does not match the verifier, client or callback, or a request with\ \ a valid CSRF token also carries the browser session cookie" "403": content: application/json: {} description: The request carries the browser session cookie without a valid CSRF token. The server refuses it before the endpoint runs. "429": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "This address sent too many installed-client requests. Wait\ \ the number of seconds in the Retry-After header, then try again." summary: Redeem a sign-in handoff code with its PKCE verifier tags: - Client session /auth/csrf: get: description: "Fetch with credentials before any other credentialed request at\ \ startup and after sign-in or sign-out. Wait for this response before starting\ \ other requests. Send the token in the returned header on unsafe requests.\ \ On a CSRF 403, refetch once and retry the rejected request once." operationId: getCsrfToken responses: "200": content: application/json: schema: $ref: "#/components/schemas/CsrfToken" description: OK summary: Get the raw CSRF token for the current browser tags: - Auth /auth/logout: post: description: An installed-client access token ends its whole session. operationId: logout responses: "200": description: OK summary: Log out — revoke the current token + clear the cookie tags: - Auth /auth/refresh: post: operationId: refresh responses: "204": description: Session renewal completed "400": description: The token belongs to an installed-client session "401": description: Session has ended summary: "Rotate the access token (new jti, old revoked)" tags: - Auth /contributors: get: description: Returns contributors to the Hephaestus project (for the About page) operationId: listGlobalContributors responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/Contributor" description: list of contributors sorted by contribution count security: [] summary: List global contributors tags: - Contributors /identity-providers: get: operationId: listIdentityProviders responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/IdentityProviderView" description: OK summary: List available identity providers tags: - Auth discovery /notifications/unsubscribe/{token}: post: operationId: unsubscribeEmail parameters: - in: path name: token required: true schema: type: string requestBody: content: application/x-www-form-urlencoded: schema: type: object properties: List-Unsubscribe: type: string required: - List-Unsubscribe multipart/form-data: schema: type: object properties: List-Unsubscribe: type: string required: - List-Unsubscribe responses: "204": description: "Subscription disabled, or token no longer applicable" security: [] summary: Unsubscribe from one optional email subscription tags: - Notification preferences /oauth/callback/{kind}: get: operationId: callbackGet parameters: - in: path name: kind required: true schema: type: string - in: query name: state required: false schema: type: string - in: query name: error required: false schema: type: string - in: query name: error_description required: false schema: type: string - in: query name: allParams required: true schema: type: object additionalProperties: type: string responses: "200": content: application/json: schema: type: object description: OK tags: - o-auth-callback post: operationId: callbackPost parameters: - in: path name: kind required: true schema: type: string - in: query name: state required: false schema: type: string - in: query name: error required: false schema: type: string - in: query name: error_description required: false schema: type: string - in: query name: allParams required: true schema: type: object additionalProperties: type: string responses: "200": content: application/json: schema: type: object description: OK tags: - o-auth-callback /product-feedback: post: operationId: submitInstanceProductFeedback requestBody: content: application/json: schema: $ref: "#/components/schemas/FeedbackRequest" required: true responses: "200": description: OK summary: Send instance-scoped product feedback tags: - instance-feedback /public/workspaces/{slug}/activity: get: operationId: getPublicActivity parameters: - in: path name: slug required: true schema: type: string - description: Activity range in: query name: range required: false schema: type: string enum: - 30d - 90d - 1y - all - custom - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time - in: query name: repo required: false schema: type: array items: type: string uniqueItems: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivity" description: Public contributions counted security: [] summary: Read human contributions to public repositories tags: - public-activity /user: delete: operationId: deleteCurrentUser parameters: - in: header name: X-Confirm-Delete required: false schema: type: string responses: "200": description: OK summary: Delete the current account (GDPR Art. 17) tags: - Account get: operationId: getCurrentUser responses: "200": content: application/json: schema: $ref: "#/components/schemas/CurrentUserView" description: OK summary: Get the current user tags: - Account /user/ai-choice: get: operationId: getAccountAiChoice responses: "200": content: application/json: schema: $ref: "#/components/schemas/AccountAiChoice" description: OK summary: Get your AI choice tags: - Account put: operationId: updateAccountAiChoice requestBody: content: application/json: schema: $ref: "#/components/schemas/AccountAiChoiceRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/AccountAiChoice" description: OK summary: Change your AI choice for every workspace you are in tags: - Account /user/consent: get: operationId: getConsentStatus responses: "200": content: application/json: schema: $ref: "#/components/schemas/ConsentStatus" description: OK summary: Get the current consent notice and status tags: - Consent put: operationId: completeFirstLoginConsent requestBody: content: application/json: schema: $ref: "#/components/schemas/FirstLoginConsent" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ConsentStatus" description: OK summary: Complete the first-login transparency step tags: - Consent /user/consent/research: put: operationId: updateResearchConsent requestBody: content: application/json: schema: $ref: "#/components/schemas/ResearchConsent" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ConsentStatus" description: OK summary: Grant or withdraw research consent tags: - Consent /user/exports: post: operationId: requestDataExport responses: "200": content: application/json: schema: $ref: "#/components/schemas/ExportCreated" description: OK summary: Request a data export (async) tags: - Account /user/exports/{id}: get: operationId: getDataExportStatus parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/ExportStatus" description: OK summary: Get data-export status tags: - Account /user/exports/{id}/download: get: operationId: downloadDataExport parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: type: string format: byte description: OK summary: Download the data-export bundle tags: - Account /user/features: get: description: Returns all feature flags evaluated for the authenticated user. Combines role checks and server-side config toggles. operationId: getUserFeatures responses: "200": content: application/json: schema: $ref: "#/components/schemas/FeatureFlags" description: Feature flags evaluated successfully summary: Get feature flags for the current user tags: - Account /user/identities: get: operationId: listLinkedIdentities responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/IdentityView" description: OK summary: List linked identity providers tags: - Account /user/identities/{id}: delete: operationId: unlinkIdentity parameters: - in: path name: id required: true schema: type: integer format: int64 responses: "204": description: Identity unlinked "404": description: No such identity on the current account "409": description: Cannot unlink the account's only remaining sign-in method summary: Unlink one of the current user's linked identity providers tags: - Account /user/notification-preferences: get: operationId: getNotificationPreferences responses: "200": content: application/json: schema: $ref: "#/components/schemas/NotificationPreferences" description: Your current email subscriptions headers: ETag: description: Strong validator for If-Match schema: type: string style: simple summary: Get your email subscriptions tags: - notification-preferences put: operationId: updateNotificationPreferences parameters: - description: Current preferences ETag in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateNotificationPreferences" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/NotificationPreferences" description: Email subscriptions updated headers: ETag: description: Strong validator for the updated preferences schema: type: string style: simple "400": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Invalid preferences or If-Match header "403": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Enabling this subscription requires instance administration "409": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Enabling email requires a verified contact on an active account "412": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The supplied ETag is stale "428": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: If-Match is required summary: Update your email subscriptions tags: - notification-preferences /user/public-activity: get: operationId: getPublicActivityChoice responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityChoice" description: OK summary: Get your account-wide public activity choice tags: - account-public-activity put: operationId: updatePublicActivityChoice requestBody: content: application/json: schema: $ref: "#/components/schemas/PublicActivityChoice" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityChoice" description: OK summary: Show or hide your activity on all public pages tags: - account-public-activity /user/public-activity/workspaces/{slug}/onboarding: get: operationId: getPublicActivityOnboarding parameters: - in: path name: slug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityOnboarding" description: OK summary: Check your public-workspace onboarding tags: - public-activity-onboarding put: operationId: answerPublicActivityOnboarding parameters: - in: path name: slug required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/PublicActivityOnboardingRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityOnboarding" description: OK summary: Show or hide yourself and finish this workspace's onboarding tags: - public-activity-onboarding /user/sessions: delete: operationId: revokeOtherSessions responses: "200": description: OK summary: Revoke all sessions except the current one tags: - Account get: operationId: listSessions responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/SessionView" description: OK summary: List active sessions for the current user tags: - Account /user/sessions/{jti}: delete: description: "Any token of an installed-client session, even one it rotated\ \ away, ends that session." operationId: revokeSession parameters: - in: path name: jti required: true schema: type: string format: uuid responses: "200": description: OK summary: Revoke a single session tags: - Account /user/settings: get: operationId: getUserSettings responses: "200": content: application/json: schema: $ref: "#/components/schemas/UserSettings" description: OK summary: Get user settings tags: - Account post: operationId: updateUserSettings requestBody: content: application/json: schema: $ref: "#/components/schemas/UserSettings" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/UserSettings" description: OK summary: Update user settings tags: - Account /user/slack/preferences: get: operationId: getSlackUserPreferences responses: "200": content: application/json: schema: $ref: "#/components/schemas/SlackUserPreferences" description: OK summary: Get current user's Slack preferences tags: - Slack User Preferences /workspaces: get: operationId: listWorkspaces responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/WorkspaceListItem" description: Workspace list summary: List all workspaces tags: - workspace-registry post: operationId: createWorkspace requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateWorkspaceRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/Workspace" description: Workspace created summary: Create a new workspace tags: - workspace-registry /workspaces/gitlab/groups: post: operationId: listGitLabGroups requestBody: content: application/json: schema: $ref: "#/components/schemas/GitLabPreflightRequest" required: true responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/GitLabGroup" description: Accessible groups summary: List GitLab groups accessible to a PAT tags: - git-lab-preflight /workspaces/gitlab/preflight: post: operationId: gitLabPreflight requestBody: content: application/json: schema: $ref: "#/components/schemas/GitLabPreflightRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/GitLabPreflightResponse" description: Validation result summary: Validate a GitLab PAT before workspace creation tags: - git-lab-preflight /workspaces/providers: get: description: Returns available workspace providers with their configuration. Public endpoint — no authentication required. operationId: getProviders responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceProviders" description: OK security: [] summary: List available workspace creation providers tags: - workspace-registry /workspaces/{workspaceSlug}: delete: operationId: purgeWorkspace parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "204": description: Workspace purged summary: Permanently delete a workspace and purge its data tags: - workspace get: operationId: getWorkspace parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/Workspace" description: Workspace returned summary: Fetch a workspace by slug tags: - workspace /workspaces/{workspaceSlug}/activity/hidden-contributors: get: operationId: listHiddenContributors parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/UserInfo" description: Hidden contributors listed "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: List the contributors without a membership whom an admin hid from activity tags: - Activity /workspaces/{workspaceSlug}/activity/members/{login}/open-work: get: description: "Review requests, open pull requests and assigned issues, most\ \ recently updated first. Pull requests carry their reviewers." operationId: getOpenWork parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: The member's login in: path name: login required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/OpenWork" description: Open work listed "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: List what is open for a member tags: - Activity /workspaces/{workspaceSlug}/activity/people: get: operationId: getActivityPeople parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: Activity range in: query name: range required: false schema: type: string enum: - 30d - 90d - 1y - all - custom - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time - in: query name: team required: false schema: type: string - in: query name: repo required: false schema: type: array items: type: string uniqueItems: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ActivityPeople" description: Contributors counted "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: Count each contributor and automation account in one response tags: - Activity /workspaces/{workspaceSlug}/activity/people/{userId}: get: operationId: getActivityPerson parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: userId required: true schema: type: integer format: int64 - description: Activity range in: query name: range required: false schema: type: string enum: - 30d - 90d - 1y - all - custom - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time - in: query name: team required: false schema: type: string - in: query name: repo required: false schema: type: array items: type: string uniqueItems: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ActivityPersonDetail" description: Contributor activity counted "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: "Count a contributor by week, type and repository" tags: - Activity /workspaces/{workspaceSlug}/activity/people/{userId}/automation: patch: operationId: updateActivityAutomation parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: userId required: true schema: type: integer format: int64 - in: query name: treatAsAutomation required: true schema: type: boolean responses: "204": description: Automation classification updated "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: "Treat a contributor as automation, or reset the classification" tags: - Activity /workspaces/{workspaceSlug}/activity/people/{userId}/public-visibility: patch: operationId: updatePublicActivityObjection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: userId required: true schema: type: integer format: int64 - in: query name: hidden required: true schema: type: boolean responses: "204": description: Contributor visibility updated "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: "Honor a contributor publication objection, or restore workspace visibility" tags: - Activity /workspaces/{workspaceSlug}/activity/people/{userId}/work: get: operationId: getActivityPersonWork parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: userId required: true schema: type: integer format: int64 - description: Activity range in: query name: range required: false schema: type: string enum: - 30d - 90d - 1y - all - custom - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time - in: query name: team required: false schema: type: string - in: query name: repo required: false schema: type: array items: type: string uniqueItems: true - description: Kinds of activity to list (repeatable); omit for every kind in: query name: kinds required: false schema: type: array items: type: string enum: - PULL_REQUEST_OPENED - PULL_REQUEST_MERGED - PULL_REQUEST_CLOSED - REVIEW_APPROVED - REVIEW_CHANGES_REQUESTED - REVIEW_COMMENTED - COMMENTED - CODE_COMMENTED - ISSUE_OPENED - ISSUE_CLOSED uniqueItems: true - description: The previous page's nextCursor; omit for the first page in: query name: cursor required: false schema: type: string - description: Page size from 1 to 100; defaults to 30 in: query name: size required: false schema: type: integer format: int32 maximum: 100 minimum: 1 responses: "200": content: application/json: schema: $ref: "#/components/schemas/ActivityWorkPage" description: One page of contributor work "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: List a contributor's work one page at a time tags: - Activity /workspaces/{workspaceSlug}/activity/public-hidden-count: get: operationId: getPublicActivityHiddenCount parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityHiddenCount" description: Hidden contributors counted "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: Count hidden public contributors without identifying them tags: - Activity /workspaces/{workspaceSlug}/activity/work: get: description: "One member's activity when login is given, otherwise everyone's\ \ in the workspace or the team. With both, the member's activity within the\ \ team's scope. Each pull request or issue is listed once, by its latest activity\ \ in the range, newest first." operationId: getActivityWork parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: login required: false schema: type: string - in: query name: team required: false schema: type: string - in: query name: repo required: false schema: type: array items: type: string uniqueItems: true - description: Activity range in: query name: range required: false schema: type: string enum: - 30d - 90d - 1y - all - custom - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time - description: Kinds of activity to list (repeatable); omit for every kind in: query name: kinds required: false schema: type: array items: type: string enum: - PULL_REQUEST_OPENED - PULL_REQUEST_MERGED - PULL_REQUEST_CLOSED - REVIEW_APPROVED - REVIEW_CHANGES_REQUESTED - REVIEW_COMMENTED - COMMENTED - CODE_COMMENTED - ISSUE_OPENED - ISSUE_CLOSED uniqueItems: true - description: The previous page's nextCursor; omit for the first page in: query name: cursor required: false schema: type: string - description: Page size from 1 to 100; defaults to 30 in: query name: size required: false schema: type: integer format: int32 maximum: 100 minimum: 1 responses: "200": content: application/json: schema: $ref: "#/components/schemas/ActivityWorkPage" description: One page of work "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A request parameter is not valid "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of the workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Workspace, contributor, team or repository not found" summary: "List activity by the pull request or issue it happened on, one page\ \ at a time" tags: - Activity /workspaces/{workspaceSlug}/agents: get: operationId: listAgents parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/AgentBinding" description: Bindings returned summary: List the workspace's agents and how each is configured tags: - Agents /workspaces/{workspaceSlug}/agents/jobs: get: operationId: listAgentJobs parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: Filter by job status in: query name: status required: false schema: type: string enum: - QUEUED - RUNNING - COMPLETED - FAILED - TIMED_OUT - CANCELLED - in: query name: page required: false schema: type: integer format: int32 default: 0 - in: query name: size required: false schema: type: integer format: int32 default: 20 responses: "200": content: application/json: schema: $ref: "#/components/schemas/PageResponseDTOAgentJob" description: Paginated job list summary: List agent jobs for a workspace tags: - Agent Jobs /workspaces/{workspaceSlug}/agents/jobs/{jobId}: get: operationId: getAgentJob parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: jobId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/AgentJob" description: Job detail returned "404": description: Job not found in this workspace summary: Get agent job details tags: - Agent Jobs /workspaces/{workspaceSlug}/agents/jobs/{jobId}/cancel: post: operationId: cancelAgentJob parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: jobId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/AgentJob" description: Job cancelled "404": description: Job not found in this workspace "409": description: Job already in terminal state summary: Cancel an agent job tags: - Agent Jobs /workspaces/{workspaceSlug}/agents/jobs/{jobId}/delivery/retry: post: operationId: retryAgentJobDelivery parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: jobId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/AgentJob" description: Delivery retried "404": description: Job not found in this workspace "409": description: Job not in a retryable state summary: Retry delivery for a completed agent job tags: - Agent Jobs /workspaces/{workspaceSlug}/agents/{purpose}: delete: operationId: deleteAgent parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: purpose required: true schema: type: string enum: - PRACTICE_REVIEW - MENTOR - in: query name: dataHandlingTier required: false schema: type: string default: UNDECLARED enum: - IN_HOUSE - CLOUD - UNDECLARED responses: "204": description: Binding removed summary: Remove the agent for one purpose (turn it off) tags: - Agents put: operationId: configureAgent parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: purpose required: true schema: type: string enum: - PRACTICE_REVIEW - MENTOR - in: query name: dataHandlingTier required: false schema: type: string default: UNDECLARED enum: - IN_HOUSE - CLOUD - UNDECLARED requestBody: content: application/json: schema: $ref: "#/components/schemas/AgentBindingRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/AgentBinding" description: Binding saved "404": description: Model not found "409": description: "The model is undeclared, or declared as another tier than\ \ this slot (problem type agent-binding-slot-mismatch, property declaredTier)" summary: Configure the agent for one purpose tags: - Agents /workspaces/{workspaceSlug}/config-audit: get: operationId: listWorkspaceConfigAuditEvents parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: page required: false schema: type: integer format: int32 default: 0 - in: query name: size required: false schema: type: integer format: int32 default: 50 - in: query name: entityType required: false schema: type: array items: type: string enum: - PRACTICE_REVIEW_SETTINGS - AGENT_BINDING - AGENT_CONFIG - AI_CONFIG_BINDING - WORKSPACE_ROLE - ACTIVITY_AUTOMATION - WORKSPACE_FEATURES - WORKSPACE_STATUS - WORKSPACE_TOKEN - WORKSPACE_VISIBILITY - PRACTICE_ACTIVE - PRACTICE_USAGE - PRACTICE_DEFINITION - PRACTICE_GROUP - CURATED_PRACTICE - CURATED_PRACTICE_GROUP - WORKSPACE_INSTANCE_LLM_BUDGET - WORKSPACE_OWN_PROVIDER_LLM_BUDGET - WORKSPACE_LLM_BUDGET - WORKSPACE_BYO_LLM_BUDGET - REVIEW_BACKFILL_RUN - REVIEW_SWEEP_SCHEDULE - WORKSPACE_LLM_CONNECTION - WORKSPACE_LLM_MODEL - in: query name: entityId required: false schema: type: string - in: query name: changedKey required: false schema: type: string - in: query name: action required: false schema: type: array items: type: string enum: - CREATED - UPDATED - DELETED - in: query name: actorId required: false schema: type: integer format: int64 - in: query name: from required: false schema: type: string format: date-time - in: query name: to required: false schema: type: string format: date-time responses: "200": content: application/json: schema: $ref: "#/components/schemas/PageResponseDTOConfigAuditEntryView" description: OK summary: "List this workspace's admin configuration changes (paged, newest first)" tags: - Config Audit /workspaces/{workspaceSlug}/connections: get: operationId: list parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/ConnectionSummary" description: OK tags: - Connections post: operationId: initiate parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/InitiateConnectionRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/InitiateConnectionResponse" description: OK tags: - Connections /workspaces/{workspaceSlug}/connections/catalog: get: operationId: getIntegrationCatalog parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/IntegrationCatalogEntry" description: OK summary: "Every integration kind this workspace could connect, joined against\ \ existing connections" tags: - Sync /workspaces/{workspaceSlug}/connections/outline/token: get: description: "Probes Outline directly. Reports whether the token is still accepted\ \ and, when the token may list its own key, its name, expiry and last use.\ \ Outline cannot rotate a key from a key, so an expiring token is renewed\ \ in Outline and re-entered here." operationId: getOutlineTokenStatus parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/OutlineTokenStatus" description: Token state returned "404": description: The workspace has no ACTIVE Outline connection summary: Live state of the API token behind this workspace's Outline connection tags: - Connections /workspaces/{workspaceSlug}/connections/{connectionId}/sync: get: operationId: getConnectionSyncStatus parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: connectionId required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/ConnectionSyncStatus" description: OK summary: Unified sync status for one connection tags: - Sync /workspaces/{workspaceSlug}/connections/{connectionId}/sync/jobs: get: operationId: listConnectionSyncJobs parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: connectionId required: true schema: type: integer format: int64 - in: query name: page required: false schema: type: integer format: int32 default: 0 - in: query name: size required: false schema: type: integer format: int32 default: 20 responses: "200": content: application/json: schema: $ref: "#/components/schemas/PageResponseDTOSyncJob" description: OK summary: Paginated sync job history for one connection tags: - Sync post: description: |- Trigger a manual sync. Idempotent-absorb: a connection that already has an active job answers 200 with that job rather than erroring, so a double-click "Sync now" is harmless. operationId: triggerSyncJob parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: connectionId required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/TriggerSyncJobRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/SyncJob" description: "Idempotent-absorb: a same-type job was already running and\ \ is returned unchanged" "202": content: application/json: schema: $ref: "#/components/schemas/SyncJob" description: A new sync job was created and dispatched "400": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Missing or invalid request body (e.g. absent sync type) "404": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Connection not found in this workspace "409": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Connection is not ACTIVE, a different sync type is already\ \ running, or manual sync is unsupported for the kind" "503": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The server is too busy to dispatch the sync; retry later summary: Trigger a manual sync or backfill tags: - Sync /workspaces/{workspaceSlug}/connections/{connectionId}/sync/jobs/{jobId}: patch: operationId: updateConnectionSyncJob parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: connectionId required: true schema: type: integer format: int64 - in: path name: jobId required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateSyncJobRequest" required: true responses: "202": content: application/json: schema: $ref: "#/components/schemas/SyncJob" description: Cancellation requested; the running job stops cooperatively "400": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: The update does not request cancellation "404": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Job not found in this workspace, or not owned by this connection" "409": content: application/json: schema: $ref: "#/components/schemas/ProblemDetail" description: Job is already in a terminal status summary: Update a running sync job tags: - Sync /workspaces/{workspaceSlug}/connections/{connectionId}/sync/resources: get: operationId: listConnectionSyncResources parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: connectionId required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/SyncResourceState" description: OK summary: Per-resource sync state (repos / channels / collections) for one connection tags: - Sync /workspaces/{workspaceSlug}/connections/{id}: get: operationId: read parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/ConnectionDetail" description: OK tags: - Connections /workspaces/{workspaceSlug}/connections/{id}/audit: get: operationId: audit parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/ConnectionAuditEntry" description: OK tags: - Connections /workspaces/{workspaceSlug}/connections/{id}/status: patch: description: |- Resource-oriented lifecycle transition: ACTIVE (reactivate), SUSPENDED (suspend), or UNINSTALLED (disconnect). Disconnecting erases the integration's mirrored data and then, best effort, removes what it installed at the provider; if the erase fails, the connection is left unchanged. PENDING is internal to the OAuth handshake and rejected as a bad request; illegal transitions surface as 409 via the state machine. operationId: updateConnectionStatus parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateConnectionStatusRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ConnectionSummary" description: OK summary: |- Resource-oriented lifecycle transition: ACTIVE (reactivate), SUSPENDED (suspend), or UNINSTALLED (disconnect). tags: - Connections /workspaces/{workspaceSlug}/features: patch: operationId: updateFeatures parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateWorkspaceFeaturesRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Workspace" description: Workspace updated summary: Update workspace feature flags tags: - workspace /workspaces/{workspaceSlug}/llm/available-models: get: operationId: workspaceListAvailableLlmModels parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/AvailableLlmModel" description: OK summary: List models this workspace can bind a Task to (shared + your own) tags: - Workspace LLM /workspaces/{workspaceSlug}/llm/budget: put: operationId: updateWorkspaceLlmBudget parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateLlmBudgetRequest" required: true responses: "204": description: Cap updated summary: Set or clear this workspace's monthly cap on its own-provider LLM spend tags: - LLM Usage /workspaces/{workspaceSlug}/llm/connections: get: operationId: workspaceListLlmConnections parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/WorkspaceLlmConnection" description: OK summary: List your AI provider connections tags: - Workspace LLM post: operationId: workspaceCreateLlmConnection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateWorkspaceLlmConnectionRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmConnection" description: Connection created; URL in the Location header "409": description: A connection with this slug already exists in this workspace summary: Connect your own AI provider tags: - Workspace LLM /workspaces/{workspaceSlug}/llm/connections/{connectionId}/models: post: operationId: workspaceCreateLlmModel parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: connectionId required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateWorkspaceLlmModelRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmModel" description: Model created; URL in the Location header "404": description: AI provider connection not found "409": description: A model with this slug or upstream model id already exists on the connection summary: Create a model on your AI provider tags: - Workspace LLM /workspaces/{workspaceSlug}/llm/connections/{id}: delete: operationId: workspaceDeleteLlmConnection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 responses: "204": description: Connection removed "404": description: Connection not found "409": description: Cannot delete a connection still referenced by one or more models summary: Remove your AI provider connection tags: - Workspace LLM get: operationId: workspaceGetLlmConnection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmConnection" description: OK "404": description: Connection not found summary: Get one of your AI provider connections tags: - Workspace LLM patch: operationId: workspaceUpdateLlmConnection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateWorkspaceLlmConnectionRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmConnection" description: OK "404": description: Connection not found summary: Update your AI provider connection tags: - Workspace LLM /workspaces/{workspaceSlug}/llm/connections/{id}/probe: post: operationId: workspaceProbeLlmConnection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmProbeResult" description: OK summary: Test your AI provider connection tags: - Workspace LLM /workspaces/{workspaceSlug}/llm/models: get: operationId: workspaceListLlmModels parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/WorkspaceLlmModel" description: OK summary: List models on your AI provider tags: - Workspace LLM /workspaces/{workspaceSlug}/llm/models/{id}: delete: operationId: workspaceDeleteLlmModel parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 responses: "204": description: Model removed "404": description: Model not found "409": description: Cannot delete a model still bound to an agent configuration summary: Remove a model on your AI provider tags: - Workspace LLM get: operationId: workspaceGetLlmModel parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmModel" description: OK "404": description: Model not found summary: Get a model on your AI provider tags: - Workspace LLM patch: operationId: workspaceUpdateLlmModel parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: id required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateWorkspaceLlmModelRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmModel" description: OK "404": description: Model not found "409": description: Another model on the connection already uses this upstream model id summary: Update a model on your AI provider tags: - Workspace LLM /workspaces/{workspaceSlug}/llm/settings: get: operationId: workspaceGetLlmSettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmSettings" description: OK summary: Get the instance LLM policy as it applies to this workspace tags: - Workspace LLM /workspaces/{workspaceSlug}/llm/usage: get: operationId: getLlmUsageReport parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: month required: false schema: type: string pattern: "\\d{4}-(0[1-9]|1[0-2])" responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceLlmUsageReport" description: OK summary: Get the workspace's LLM usage report for one month tags: - LLM Usage /workspaces/{workspaceSlug}/members: get: operationId: listMembers parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: Zero-based page index in: query name: page required: false schema: type: integer format: int32 default: 0 minimum: 0 - description: "Results per page, capped at 100" in: query name: size required: false schema: type: integer format: int32 default: 50 minimum: 1 responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/WorkspaceMembership" description: OK tags: - workspace-membership /workspaces/{workspaceSlug}/members/assign: post: operationId: assignRole parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/AssignRoleRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceMembership" description: OK tags: - workspace-membership /workspaces/{workspaceSlug}/members/me: get: description: "One representative membership, with the account's effective workspace\ \ role." operationId: getCurrentUserMembership parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceMembership" description: OK summary: "One representative membership, with the account's effective workspace\ \ role." tags: - workspace-membership /workspaces/{workspaceSlug}/members/{userId}: delete: operationId: removeMember parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: userId required: true schema: type: integer format: int64 responses: "204": description: Membership removed tags: - workspace-membership get: operationId: getMember parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: userId required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceMembership" description: OK tags: - workspace-membership /workspaces/{workspaceSlug}/members/{userId}/hidden: patch: operationId: updateMemberVisibility parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: userId required: true schema: type: integer format: int64 - description: Whether to leave the member out of workspace activity in: query name: hidden required: true schema: type: boolean responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceMembership" description: OK tags: - workspace-membership /workspaces/{workspaceSlug}/mentor/sandbox: post: operationId: prepareMentorSandbox parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "202": description: Accepted; the sandbox starts unless it is already warm or Heph could not answer anyway summary: Prepare the current member's Heph sandbox in the background tags: - Mentor Chat /workspaces/{workspaceSlug}/mentor/threads: get: operationId: listThreads parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/ChatThreadSummary" description: "Threads returned, newest first" summary: List the current user's mentor threads in this workspace tags: - Mentor Threads /workspaces/{workspaceSlug}/mentor/threads/{threadId}: delete: operationId: deleteThread parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: threadId required: true schema: type: string format: uuid responses: "204": description: Thread deleted "404": description: Thread not found OR not owned by current user summary: "Delete a mentor thread (cascades to messages, votes, parts)" tags: - Mentor Threads get: operationId: getThread parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: threadId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/ChatThreadDetail" description: "Thread, messages and the owner's votes returned" "404": description: Thread not found OR not owned by current user summary: Get a mentor thread with its full message history tags: - Mentor Threads /workspaces/{workspaceSlug}/mentor/threads/{threadId}/messages/{messageId}/vote: delete: operationId: removeVote parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: threadId required: true schema: type: string format: uuid - in: path name: messageId required: true schema: type: string format: uuid responses: "204": description: Vote removed or did not exist "404": description: Thread or message not found (or not owned by current user) summary: Remove a vote on an assistant message (idempotent) tags: - Mentor Votes post: operationId: vote parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: threadId required: true schema: type: string format: uuid - in: path name: messageId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/ChatMessageVoteRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ChatMessageVote" description: Vote recorded "404": description: Thread or message not found (or not owned by current user) summary: Upsert a vote on an assistant message tags: - Mentor Votes /workspaces/{workspaceSlug}/onboarding/me: get: operationId: getMemberOnboarding parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceOnboarding" description: OK summary: Get your first-visit setup and AI choice in this workspace tags: - workspace-onboarding /workspaces/{workspaceSlug}/onboarding/me/ai-choice: put: operationId: updateMemberAiChoice parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/MemberAiChoiceRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceOnboarding" description: OK summary: Change your AI choice without changing workspace membership tags: - workspace-onboarding /workspaces/{workspaceSlug}/onboarding/me/dismissal: put: operationId: dismissMemberOnboarding parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceOnboarding" description: OK summary: Skip first-visit setup for now without treating that as an AI choice tags: - workspace-onboarding /workspaces/{workspaceSlug}/onboarding/settings: get: operationId: getMemberOnboardingSettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceOnboardingSettings" description: OK summary: Get this workspace's member-onboarding settings tags: - workspace-onboarding put: operationId: updateMemberOnboardingSettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/WorkspaceOnboardingSettings" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceOnboardingSettings" description: OK summary: Configure first-visit setup and required workspace account links tags: - workspace-onboarding /workspaces/{workspaceSlug}/onboarding/settings/links: get: operationId: getMemberOnboardingLinkOptions parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/WorkspaceOnboardingLink" description: OK summary: List workspace account links available for onboarding requirements tags: - workspace-onboarding /workspaces/{workspaceSlug}/outline/collections: get: operationId: listOutlineCollections parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/OutlineCollection" description: Mirrored collections returned "404": description: The workspace has no ACTIVE Outline connection summary: List the workspace's mirrored Outline collections with their sync state tags: - Outline collections post: operationId: registerOutlineCollection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/RegisterOutlineCollectionRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/OutlineCollection" description: Collection was already registered (idempotent repeat) "201": content: application/json: schema: $ref: "#/components/schemas/OutlineCollection" description: Collection registered; the Location header points at the collection resource "404": description: The workspace has no ACTIVE Outline connection "409": description: A concurrent registration of the same collection won the race "422": description: Outline does not know the requested collection id summary: Register an Outline collection for mirroring (lands ENABLED + PENDING; idempotent on the id) tags: - Outline collections /workspaces/{workspaceSlug}/outline/collections/candidates: get: description: "Proxies Outline's collections.list with the stored token under\ \ a bounded interactive page budget. Served with Cache-Control: no-store —\ \ the live upstream view must not be cached." operationId: listOutlineCollectionCandidates parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/OutlineCollectionCandidate" description: "Candidate collections returned (Cache-Control: no-store)" "404": description: The workspace has no ACTIVE Outline connection "502": description: The Outline server could not be reached or answered with an error "503": description: Outline limited the request rate. The Retry-After header carries the seconds to wait before retrying. summary: List the Outline collections available to mirror (live proxy; doubles as connectivity probe) tags: - Outline collections /workspaces/{workspaceSlug}/outline/collections/{collectionId}: delete: operationId: deleteOutlineCollection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: collectionId required: true schema: type: string responses: "204": description: Collection removed and its mirrored documents erased "404": description: "The collection is not registered for this workspace, or the\ \ workspace has no ACTIVE Outline connection" summary: Remove a collection from the mirror and erase its mirrored documents (terminal) tags: - Outline collections get: operationId: getOutlineCollection parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: collectionId required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/OutlineCollection" description: Mirrored collection returned "404": description: "The collection is not registered for this workspace, or the\ \ workspace has no ACTIVE Outline connection" summary: One mirrored Outline collection with its sync state and live document count tags: - Outline collections patch: description: Resuming (PAUSED → ENABLED) resets the sync status to PENDING and kicks a targeted sync; requesting the current state is an idempotent no-op. operationId: updateOutlineCollectionState parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: collectionId required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateOutlineCollectionStateRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/OutlineCollection" description: Collection state after the transition returned "404": description: "The collection is not registered for this workspace, or the\ \ workspace has no ACTIVE Outline connection" summary: Transition a mirrored collection to a target mirror state (pause / resume) tags: - Outline collections /workspaces/{workspaceSlug}/practice-catalog/adoption: get: operationId: listAdoptablePractices parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/CatalogPracticeSummary" description: Available practices returned "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Workspace administrator access is required summary: List practices available for adoption tags: - Practice Catalog Adoption /workspaces/{workspaceSlug}/practice-catalog/adoption/groups/{slug}: get: operationId: previewGroupAdoption parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CatalogGroupAdoptionPreview" description: OK summary: Preview adoption of a catalog group and its practices tags: - Practice Catalog Adoption post: operationId: adoptGroup parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slug required: true schema: type: string - in: header name: If-Match required: false schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CatalogGroupAdoptionResult" description: OK summary: Adopt all available practices in a catalog group tags: - Practice Catalog Adoption /workspaces/{workspaceSlug}/practice-catalog/adoption/{slug}: get: operationId: previewPracticeAdoption parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CatalogPracticePreview" description: Adoption preview returned headers: ETag: description: Strong validator for If-Match style: simple "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Workspace administrator access is required "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice is not offered summary: Get a practice adoption preview tags: - Practice Catalog Adoption post: operationId: adoptPractice parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slug required: true schema: type: string - in: header name: If-Match required: false schema: type: string responses: "201": content: application/json: schema: $ref: "#/components/schemas/Practice" description: Practice adopted "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Workspace administrator access is required "409": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The practice slug already exists in the workspace "412": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Catalog or workspace state changed since preview "428": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The If-Match preview validator is required summary: Adopt a catalog practice tags: - Practice Catalog Adoption /workspaces/{workspaceSlug}/practice-catalog/practices/{slug}: get: description: The current instance-catalog definition for comparison with a workspace copy. operationId: getCuratedPracticeCatalogEntry parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/CuratedPractice" description: OK summary: Read the instance's definition of a practice tags: - Practice Catalog /workspaces/{workspaceSlug}/practice-groups: get: description: Returns the workspace's practice groups operationId: listGroups parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: Return only groups shown in practice dashboards in: query name: visibleInPracticeDashboardsOnly required: false schema: type: boolean responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/PracticeGroup" description: Groups returned summary: List practice groups tags: - Practice Groups post: operationId: createGroup parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/CreatePracticeGroupRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/PracticeGroup" description: Group created "409": description: Group slug already exists in this workspace summary: Create a new practice group tags: - Practice Groups /workspaces/{workspaceSlug}/practice-groups/reorder: patch: description: Sets each group's display order to its index in the provided slug list (one atomic write) operationId: reorderGroups parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/ReorderPracticeGroupsRequest" required: true responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/PracticeGroup" description: Groups reordered; the full ordered list is returned "400": description: orderedSlugs is empty or contains duplicates "404": description: A slug is unknown summary: Reorder practice groups tags: - Practice Groups /workspaces/{workspaceSlug}/practice-groups/standings: get: description: "Returns every active practice group's standing, direction, guidance,\ \ and supporting observations." operationId: listPracticeGroupStandings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/PracticeGroupStanding" description: Practice group standings returned summary: List the current developer's practice group standings tags: - Practice Group Standings /workspaces/{workspaceSlug}/practice-groups/{groupSlug}: delete: description: Deletes the group. By default its practices move to Unassigned; deletePractices=true deletes them too. operationId: deleteGroup parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: groupSlug required: true schema: type: string - in: query name: deletePractices required: false schema: type: boolean default: false responses: "204": description: Group deleted "404": description: Group not found summary: Delete a practice group tags: - Practice Groups get: operationId: getGroup parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: groupSlug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeGroup" description: Group returned "404": description: Group not found summary: Get a practice group tags: - Practice Groups patch: operationId: updateGroup parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: groupSlug required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdatePracticeGroupRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeGroup" description: Group updated "404": description: Group not found summary: Update a practice group tags: - Practice Groups /workspaces/{workspaceSlug}/practice-groups/{groupSlug}/autonomy: patch: description: "Applies to every practice in the group that holds no autonomy\ \ of its own; practices that set their own are left alone. OFF stops their\ \ reviews entirely. HUMAN_APPROVAL runs them and records every observation,\ \ holds feedback on the work for an authorized reviewer, and still writes\ \ the developer's practice pages and the mentor, which are read on request.\ \ AUTOMATIC sends feedback on the work without asking. Send a null autonomy\ \ to clear the group's own setting so it follows the workspace default." operationId: setGroupAutonomy parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: groupSlug required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdatePracticeAutonomyRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeGroup" description: Autonomy updated; the response carries the autonomy now in force and where it came from "404": description: Group not found summary: Set how much autonomy the system has over one group tags: - Practice Groups /workspaces/{workspaceSlug}/practice-groups/{groupSlug}/review-runs: get: description: "Returns complete review runs newest first, including visible undecided\ \ observations." operationId: listPracticeGroupReviewRuns parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: groupSlug required: true schema: type: string - in: query name: practiceSlug required: false schema: type: string - description: "Only reviews of these artifact kinds, e.g. scm.pull_request\ \ (repeatable)" in: query name: artifactKinds required: false schema: type: array items: type: string - in: query name: severities required: false schema: type: array items: type: string enum: - CRITICAL - MAJOR - MINOR - INFO - description: "Zero-based page, at most 100" in: query name: page required: false schema: type: integer format: int32 maximum: 100 minimum: 0 - description: Page size from 1 to 50 in: query name: size required: false schema: type: integer format: int32 maximum: 50 minimum: 1 responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeGroupReviewRunsPage" description: Paginated review runs returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Invalid filter or pagination "404": description: Practice group not found summary: List complete review runs for a practice group tags: - Practice Group Detail /workspaces/{workspaceSlug}/practice-groups/{groupSlug}/trend: get: description: Returns the group direction and every eligible practice direction with inspectable support. operationId: getPracticeGroupTrend parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: groupSlug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeGroupTrend" description: Practice-group trend returned "404": description: Practice group not found summary: Get the evidence-supported trend for a practice group tags: - Practice Group Detail /workspaces/{workspaceSlug}/practice-profile/overview: get: description: "Returns the practices met as a strength, every change to a standing,\ \ trend, group or piece of feedback inside the window, and the work reviewed\ \ inside it, as structured events. The window opens at the run before the\ \ latest one and closes now; with no such run it spans the standing's look-back\ \ of 90 days." operationId: getPracticeProfileOverview parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeProfileOverview" description: Practice profile overview returned summary: "What was met, what changed and which work was reviewed since the run\ \ before the latest one" tags: - Practice Profile /workspaces/{workspaceSlug}/practice-profile/review-runs: get: description: "One row per run that recorded an observation about the calling\ \ developer, across every practice group, with what that run found about them.\ \ Counts are narrowed to this developer: a run over shared work says nothing\ \ here about anybody else." operationId: listPracticeProfileReviewRuns parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: "Zero-based page, at most 100" in: query name: page required: false schema: type: integer format: int32 maximum: 100 minimum: 0 - description: Page size from 1 to 50 in: query name: size required: false schema: type: integer format: int32 maximum: 50 minimum: 1 - description: "Restrict to one kind of work, e.g. scm.pull_request" in: query name: kind required: false schema: type: string - description: Keep only runs whose newest observation about this developer came after this moment; the bound is exclusive in: query name: since required: false schema: type: string format: date-time responses: "200": content: application/json: schema: $ref: "#/components/schemas/ProfileReviewRunsPage" description: Review runs returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Unknown kind of work or invalid pagination summary: "Every review run on the developer's own work, newest first" tags: - Practice Profile /workspaces/{workspaceSlug}/practice-profile/review-runs/{reviewId}: get: description: "A run that recorded nothing about the calling developer is not\ \ theirs to read and answers 404, the same answer a run in another workspace\ \ gets." operationId: getPracticeProfileReviewRun parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: "The review, as the list names it" in: path name: reviewId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/ProfileReviewRunDetail" description: Review run returned "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: No run with anything about the calling developer in this workspace summary: "One review run on the developer's own work, with what it observed\ \ about them" tags: - Practice Profile /workspaces/{workspaceSlug}/practices: get: description: "Returns this workspace's practices, each with the autonomy in\ \ force for it, whether that autonomy was set on the practice or inherited\ \ from its group or the workspace, and which level decided it. Optionally\ \ narrowed to one autonomy." operationId: listPractices parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: "Keep only the practices whose autonomy IN FORCE is exactly this\ \ one, inherited or not" in: query name: autonomy required: false schema: type: string enum: - "OFF" - HUMAN_APPROVAL - AUTOMATIC responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/Practice" description: Practices returned summary: List practice definitions tags: - Practice Catalog post: operationId: createPractice parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/CreatePracticeRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/Practice" description: Practice created "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice group not found "409": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice slug already exists in this workspace summary: Create a new practice definition tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/autonomy: get: description: "How many practices sit at each autonomy, for the whole workspace\ \ and for each group, plus the workspace default and where feedback may go.\ \ The summary a hundred-practice catalogue is read through — answered here\ \ so a client never has to fetch every practice to count them." operationId: autonomyRollup parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/AutonomyRollup" description: Rollup returned summary: "Summarise how much autonomy this workspace grants, by group" tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/backfill-runs: get: operationId: listBackfillRuns parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/ReviewBackfillRun" description: Campaigns returned summary: List this workspace's recent backfill campaigns tags: - Practice Review Backfill post: description: Creates a run awaiting confirmation. Submits nothing and spends nothing. operationId: preflightBackfillRun parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateReviewBackfillRunRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/ReviewBackfillRun" description: Scope enumerated and priced "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "The window is inverted, too long, or covers too many artifacts" "409": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: A backfill is already active for this workspace summary: Enumerate and price a backfill campaign tags: - Practice Review Backfill /workspaces/{workspaceSlug}/practices/backfill-runs/{runId}: get: operationId: getBackfillRun parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: runId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewBackfillRun" description: Campaign returned "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: No such campaign in this workspace summary: "Get one backfill campaign, including its live progress" tags: - Practice Review Backfill /workspaces/{workspaceSlug}/practices/backfill-runs/{runId}/status: patch: description: RUNNING authorises the estimated spend and starts the campaign; CANCELLED stops it for good. operationId: updateBackfillRunStatus parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: runId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateReviewBackfillRunStatusRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewBackfillRun" description: Campaign updated "409": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The campaign cannot make that transition from its current state summary: Confirm or cancel a backfill campaign tags: - Practice Review Backfill /workspaces/{workspaceSlug}/practices/definition-options: get: description: "Returns available review events, recommended requirements, and\ \ allowed evidence sources by work type" operationId: getPracticeDefinitionOptions parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeDefinitionOptions" description: OK summary: Read practice definition options tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/feedback/in-app: get: description: "Process-level messages prepared for the authenticated developer:\ \ for each way of working that recurs in their work, what the pattern is,\ \ the pieces of work it was observed on, and one thing to try next. Distinct\ \ from in-context notes (which say what is wrong in one diff) and from the\ \ mentor conversation (which asks rather than tells). Reading a message is\ \ what delivers it, so this GET records the delivery." operationId: getInAppFeedback parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/InAppFeedback" description: "In-app messages returned, newest first" summary: The current developer's in-app feedback tags: - In-App Feedback /workspaces/{workspaceSlug}/practices/feedback/on-work: get: description: "Read-only metadata for up to 50 in-context pieces of feedback\ \ addressed to the caller with recorded provider comments, newest delivery\ \ first. Uses the exact connected-provider work lookup. Only recorded successful\ \ placements are included, even when the remaining delivery failed. Incomplete\ \ units omit draft practice metadata. No bodies, private channels or replaced\ \ feedback; admin status does not broaden the recipient. Permalinks are recorded\ \ provider links, not live existence checks." operationId: getOwnDeliveredWorkFeedback parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: url required: true schema: type: string maxLength: 2048 minLength: 0 responses: "200": content: application/json: schema: $ref: "#/components/schemas/DeliveredWorkFeedback" description: OK summary: The caller's recorded feedback comments on this work tags: - Practice feedback /workspaces/{workspaceSlug}/practices/feedback/resolution-counts: get: operationId: getFeedbackResolutionCounts parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/FeedbackResolutionCounts" description: OK summary: Get feedback resolution counts tags: - Feedback Response /workspaces/{workspaceSlug}/practices/feedback/{feedbackId}/response: delete: operationId: deleteFeedbackResponse parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: feedbackId required: true schema: type: string format: uuid responses: "204": description: Response deleted or no response was recorded "404": description: Delivered feedback not found for the current recipient summary: Delete the response to delivered feedback tags: - Feedback Response get: operationId: getFeedbackResponse parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: feedbackId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/FeedbackResponse" description: Current response returned "204": description: No response is currently recorded "404": description: Delivered feedback not found for the current recipient summary: Get the current feedback response tags: - Feedback Response put: description: Sets the complete current response. Repeating the same request has no effect. operationId: replaceFeedbackResponse parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: feedbackId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/FeedbackResponseRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/FeedbackResponse" description: Response replaced "400": description: Invalid response "404": description: Delivered feedback not found for the current recipient "409": description: A workspace admin withdrew this feedback summary: Replace the response to delivered feedback tags: - Feedback Response /workspaces/{workspaceSlug}/practices/observations: get: description: Paginated observations for the authenticated developer with optional filters operationId: listObservations parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: Filter by practice slug in: query name: practiceSlug required: false schema: type: string - description: Filter by the practice group the observed practice belongs to in: query name: groupSlug required: false schema: type: string - description: Filter by review outcome in: query name: outcome required: false schema: type: string enum: - MET - NOT_MET - NOT_APPLICABLE - UNDETERMINED - description: "Only observations on these kinds of reviewed work, e.g. scm.pull_request\ \ (repeatable)" in: query name: artifactKinds required: false schema: type: array items: type: string - description: "Exact reviewed-work kind; requires artifactId, e.g. scm.pull_request\ \ or scm.issue" in: query name: artifactKind required: false schema: type: string - description: Exact reviewed-work ID; requires artifactKind in: query name: artifactId required: false schema: type: integer format: int64 exclusiveMinimum: 0 - description: Only observations with these severities (repeatable); omit for all in: query name: severities required: false schema: type: array items: type: string enum: - CRITICAL - MAJOR - MINOR - INFO - description: Drop NOT_APPLICABLE rows — only observations where the practice actually applied in: query name: displayableOnly required: false schema: type: boolean - description: "Feed ordering: DATE (default) or SEVERITY (most severe first,\ \ ties newest-first)" in: query name: sort required: false schema: type: string enum: - DATE - SEVERITY - description: "Ordering direction: for DATE newest/oldest first, for SEVERITY\ \ most/least severe first" in: query name: direction required: false schema: type: string enum: - ASC - DESC - description: Zero-based page in: query name: page required: false schema: type: integer format: int32 minimum: 0 - description: Page size from 1 to 100 in: query name: size required: false schema: type: integer format: int32 maximum: 100 minimum: 1 responses: "200": content: application/json: schema: $ref: "#/components/schemas/PageResponseDTOObservationList" description: Paginated observations returned summary: List observations for current user tags: - Practice Observations /workspaces/{workspaceSlug}/practices/observations/summary: get: description: Aggregated observation counts per practice for dashboard cards operationId: getSummary parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/DeveloperPracticeSummary" description: Practice summaries returned summary: Per-practice summary for current user tags: - Practice Observations /workspaces/{workspaceSlug}/practices/observations/{observationId}: get: operationId: getObservation parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: observationId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/ObservationDetail" description: Observation detail returned "404": description: Observation not found or not owned by current user summary: Get observation detail tags: - Practice Observations /workspaces/{workspaceSlug}/practices/releases: get: operationId: listPracticeReleases parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/PracticeReleaseProposal" description: OK summary: List pending practice releases tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/releases/{slug}: delete: operationId: declinePracticeRelease parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string responses: "204": description: The offered version was declined summary: Decline this version of a practice release tags: - Practice Catalog get: operationId: getPracticeRelease parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeReleaseProposal" description: OK summary: "Compare the adopted, current, and offered practice" tags: - Practice Catalog put: operationId: acceptPracticeRelease parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slug required: true schema: type: string - in: header name: If-Match required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/AcceptPracticeReleaseRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Practice" description: OK summary: Accept selected fields from a practice release tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/reorder: patch: description: Sets each practice's display order to its index in the provided slug list (one atomic write) operationId: reorderPractices parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/ReorderPracticesRequest" required: true responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/Practice" description: Practices reordered; the full ordered practice list is returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "orderedSlugs is empty, has duplicates, or is not the group's\ \ complete set" summary: Reorder the practices within a group tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/review-context: get: description: "Reads the address only: nothing is fetched from it. The address\ \ must be on the server this workspace is connected to. Every way of not finding\ \ the work — not mirrored, not monitored here, another server, deleted or\ \ confidential — is the same 404." operationId: resolveReviewContext parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: "The provider page's address, as the browser shows it" in: query name: url required: true schema: type: string maxLength: 2048 minLength: 0 responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewContext" description: "The work, and what the caller may do about it" "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Not an HTTPS address, or not the page of a pull request, merge\ \ request or issue" "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is not a member of this workspace "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: This workspace has no reviewed work at this address summary: Find the reviewed work a provider page shows tags: - Practice review requests /workspaces/{workspaceSlug}/practices/review-requests: post: description: "Answers 200 both when a review starts and when one deliberately\ \ does not; the body says which, and why. 403 only when the caller has no\ \ standing on the artifact." operationId: requestPracticeReview parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateReviewRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewRequestOutcome" description: "The ask was understood: a review is running, or the body names\ \ what stopped it" "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The artifact kind is not one that can be asked for "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller is neither the work's author or assignee nor a workspace admin "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: No such artifact in this workspace summary: Ask for a review of a piece of work now tags: - Practice review requests /workspaces/{workspaceSlug}/practices/review-settings: get: operationId: getPracticeReviewSettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeReviewSettings" description: Policy returned summary: Get the workspace's practice-review policy tags: - Practice Review Settings patch: operationId: updatePracticeReviewSettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: header name: If-Match required: false schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdatePracticeReviewSettingsRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeReviewSettings" description: Policy updated summary: Update the workspace's practice-review policy tags: - Practice Review Settings /workspaces/{workspaceSlug}/practices/review-settings/coverage-preview: post: operationId: previewCoverage parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/WorkspaceReviewScope" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeReviewCoveragePreview" description: OK summary: Preview the effective counts for proposed practice-review coverage tags: - Practice Review Settings /workspaces/{workspaceSlug}/practices/reviewed: get: description: "Returns the developer-facing name, group, rationale, and example\ \ for every practice the workspace reviews (any autonomy above OFF)" operationId: listReviewedPractices parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/ReviewedPractice" description: Developer practices returned summary: "List reviewed practices, developer-facing" tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/reviewed-work/{artifactKind}/{artifactId}/review-runs: get: description: "Complete review runs newest first, every practice group together,\ \ with each observation's feedback response." operationId: listReviewedWorkReviewRuns parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: "Kind of reviewed work, e.g. scm.pull_request" in: path name: artifactKind required: true schema: type: string - in: path name: artifactId required: true schema: type: integer format: int64 - description: "Zero-based page, at most 100" in: query name: page required: false schema: type: integer format: int32 maximum: 100 minimum: 0 - description: Page size from 1 to 50 in: query name: size required: false schema: type: integer format: int32 maximum: 50 minimum: 1 responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeGroupReviewRunsPage" description: Paginated review runs returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Unknown kind of work or invalid pagination summary: List the current developer's review runs of one piece of work tags: - Practice Group Detail /workspaces/{workspaceSlug}/practices/reviews: get: description: Results are ordered newest first. operationId: listPracticeReviews parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: page required: false schema: type: integer format: int32 default: 0 minimum: 0 - in: query name: size required: false schema: type: integer format: int32 default: 20 maximum: 100 minimum: 1 - description: Statuses to list (repeatable); omit for every status in: query name: status required: false schema: type: array items: type: string enum: - QUEUED - RUNNING - COMPLETED - FAILED - TIMED_OUT - CANCELLED - description: "Result-processing statuses to list (repeatable), such as FAILED\ \ for the reviews whose results can be processed again; omit for every review,\ \ including those without one" in: query name: resultProcessing required: false schema: type: array items: type: string enum: - PENDING - DELIVERED - FAILED - description: Inclusive lower bound on when the review was requested in: query name: from required: false schema: type: string format: date-time - description: Exclusive upper bound on when the review was requested in: query name: to required: false schema: type: string format: date-time responses: "200": content: application/json: schema: $ref: "#/components/schemas/PagedModelReviewRunSummary" description: Paginated review summaries returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Invalid filter or pagination summary: List practice reviews with observation and feedback outcomes tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/evidence-outcomes: get: description: "One entry per practice that recent reviews considered, with the\ \ sources that skipped it." operationId: listPracticeEvidenceOutcomes parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/PracticeEvidenceOutcome" description: Evidence outcomes returned summary: Summarize how each practice's evidence requirements turned out on recent reviews tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/feedback: get: description: Results include every delivery state and are ordered newest first by default. operationId: listPracticeReviewFeedback parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: page required: false schema: type: integer format: int32 default: 0 minimum: 0 - in: query name: size required: false schema: type: integer format: int32 default: 50 maximum: 100 minimum: 1 - description: Sorting strategy. NEWEST and OLDEST order by when the feedback was created; ties by id. in: query name: sort required: false schema: type: string default: NEWEST enum: - NEWEST - OLDEST - in: query name: deliveryState required: false schema: type: array items: type: string enum: - AWAITING_APPROVAL - PREPARED - PARTIALLY_DELIVERED - PARTIALLY_FAILED - DELIVERED - SUPERSEDED - SUPPRESSED - FAILED - DISCARDED - UNCONFIRMED - in: query name: suppressionReason required: false schema: type: array items: type: string enum: - VOLUME_CAPPED - COMPOSER_DEDUPED - COMPOSER_WITHHELD - REPEATS_DELIVERED_NOTE - REACTED_DISPUTED - REACTED_NOT_APPLICABLE - CONVERSATION_EXPIRED - ARTIFACT_GONE - ARTIFACT_CLOSED - ISSUE_SNAPSHOT_CHANGED - ARTIFACT_MERGED - PUBLIC_SUBJECT_INELIGIBLE - ARTIFACT_DRAFT - RECIPIENT_OPTED_OUT - EMPTY_AFTER_SANITIZE - INSTANCE_SILENCED - WORKSPACE_DISABLED - WORKSPACE_DELIVERY_PAUSED - STALE_ROLLOUT_REVISION - OUTSIDE_CURRENT_COVERAGE - APPROVAL_STALE - APPROVAL_NO_LONGER_ELIGIBLE - PRACTICE_REQUIRES_APPROVAL - BACKFILL_QUIET - OBSERVATION_INVALIDATED - REVIEWED_REVISION_CHANGED - in: query name: channel required: false schema: type: array items: type: string enum: - IN_CONTEXT - IN_CHAT - IN_APP - in: query name: agentJobId required: false schema: type: string format: uuid - description: "Kind of reviewed work, e.g. scm.pull_request" in: query name: artifactKind required: false schema: type: string - description: Artifact ID; requires artifactKind in: query name: artifactId required: false schema: type: integer format: int64 exclusiveMinimum: 0 - in: query name: recipientUserId required: false schema: type: integer format: int64 exclusiveMinimum: 0 - description: "Practices whose feedback to list (repeatable): feedback bound\ \ to an observation of any of them, in any role" in: query name: practiceSlug required: false schema: type: array items: type: string - description: Inclusive lower bound in: query name: from required: false schema: type: string format: date-time - description: Exclusive upper bound in: query name: to required: false schema: type: string format: date-time responses: "200": content: application/json: schema: $ref: "#/components/schemas/PagedModelReviewFeedback" description: Paginated feedback returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Invalid filter or pagination summary: List practice review feedback across the workspace tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/feedback/{feedbackId}: get: operationId: getPracticeReviewFeedback parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: feedbackId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewFeedbackDetail" description: Feedback detail returned "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Feedback not found in this workspace summary: "Get feedback with its stored body, observations and placements" tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/feedback/{feedbackId}/approval: get: operationId: getFeedbackProposalDecision parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: feedbackId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/FeedbackApproval" description: OK summary: Get the decision for a feedback proposal tags: - Practice reviews put: operationId: decideFeedbackProposal parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: feedbackId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/DecideFeedbackProposalRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/FeedbackApproval" description: OK summary: Approve or reject an immutable feedback proposal tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/feedback/{feedbackId}/withdrawal: patch: description: "Only practice-page feedback that is waiting to be read or already\ \ shown can be withdrawn. The developer sees that it was withdrawn, not what\ \ it said; its record and evidence stay. Restoring puts it back through the\ \ page's ordinary checks and sends nothing." operationId: updatePracticeReviewFeedbackWithdrawal parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: feedbackId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateFeedbackWithdrawalRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewFeedbackDetail" description: Feedback detail after the change "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Feedback not found in this workspace "409": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "The feedback is not on a practice page, or is not waiting\ \ to be read or shown there" summary: "Withdraw a card from a developer's practice page, or restore it" tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/observations: get: description: Results include linked feedback outcomes and are ordered newest first by default. operationId: listPracticeReviewObservations parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: page required: false schema: type: integer format: int32 default: 0 minimum: 0 - in: query name: size required: false schema: type: integer format: int32 default: 50 maximum: 100 minimum: 1 - description: "Sorting strategy. ACTIONABILITY orders NOT_MET by severity (CRITICAL,\ \ MAJOR, MINOR, INFO), then MET, then NOT_APPLICABLE and UNDETERMINED together.\ \ Within each rank, observation time and ID are descending." in: query name: sort required: false schema: type: string default: NEWEST enum: - NEWEST - ACTIONABILITY - in: query name: practiceSlug required: false schema: type: array items: type: string - in: query name: groupSlug required: false schema: type: array items: type: string - description: Review outcomes to list (repeatable) in: query name: outcome required: false schema: type: array items: type: string enum: - MET - NOT_MET - NOT_APPLICABLE - UNDETERMINED - description: "true for only the observations an admin has marked incorrect\ \ and not restored, false for only the others; omit for both" in: query name: invalidated required: false schema: type: boolean - description: "true for only the observations the developer disputes feedback\ \ about, false for only the others; omit for both" in: query name: disputed required: false schema: type: boolean - in: query name: severity required: false schema: type: array items: type: string enum: - CRITICAL - MAJOR - MINOR - INFO - in: query name: agentJobId required: false schema: type: string format: uuid - description: "Kind of reviewed work, e.g. scm.pull_request" in: query name: artifactKind required: false schema: type: string - description: Artifact ID; requires artifactKind in: query name: artifactId required: false schema: type: integer format: int64 exclusiveMinimum: 0 - in: query name: subjectUserId required: false schema: type: integer format: int64 exclusiveMinimum: 0 - description: "What occasioned the measurement: LIVE, MANUAL or BACKFILL" in: query name: origin required: false schema: type: array items: type: string enum: - LIVE - MANUAL - BACKFILL - description: Inclusive lower bound in: query name: from required: false schema: type: string format: date-time - description: Exclusive upper bound in: query name: to required: false schema: type: string format: date-time responses: "200": content: application/json: schema: $ref: "#/components/schemas/PagedModelReviewObservation" description: Paginated observations returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Invalid filter or pagination summary: List practice review observations across the workspace tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/observations/{observationId}: get: operationId: getPracticeReviewObservation parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: observationId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewObservationDetail" description: Observation detail returned "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Observation not found in this workspace summary: Get an observation with its evidence and linked feedback tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/observations/{observationId}/validity: patch: description: "Invalidating stops feedback citing the observation that has not\ \ reached anyone yet. Feedback already delivered keeps its record, and a comment\ \ already posted on the provider stays there. Restoring does not re-send anything." operationId: updatePracticeReviewObservationValidity parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: observationId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateObservationValidityRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewObservationDetail" description: Observation detail after the change "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Observation not found in this workspace "409": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The observation is already in the requested state summary: "Invalidate an observation that was wrong when recorded, or restore\ \ it" tags: - Practice reviews /workspaces/{workspaceSlug}/practices/reviews/overview: get: description: "In total, over time and by practice. Reviews count by when they\ \ were created, observations by when they were recorded and feedback by when\ \ it was created, as the review, observation and feedback lists filter them.\ \ The range is split into days, weeks or months, by its length, in the given\ \ time zone." operationId: getPracticeReviewOverview parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: Inclusive lower bound; defaults to seven days before to. A range spans at most 400 days. in: query name: from required: false schema: type: string format: date-time - description: Exclusive upper bound; defaults to now in: query name: to required: false schema: type: string format: date-time - description: "The IANA time zone whose midnights start the buckets, such as\ \ Europe/Berlin" in: query name: zone required: false schema: type: string default: UTC responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticeReviewOverview" description: Practice reviews counted "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Invalid range or time zone summary: "Count practice reviews, observations and feedback in a time range" tags: - Practice reviews /workspaces/{workspaceSlug}/practices/standings: get: description: "Returns each practice's standing, direction, supporting observations,\ \ and developer guidance." operationId: listPracticeStandings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/PracticeStanding" description: Practice standings returned summary: List the current developer's practice standings tags: - Practice Standings /workspaces/{workspaceSlug}/practices/sweep-schedules: get: operationId: listSweepSchedules parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/ReviewSweepSchedule" description: Schedules returned summary: List this workspace's sweep schedules tags: - Practice Review Sweep post: description: Authorises the recurring spend. The first sweep runs within the hour. operationId: createSweepSchedule parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateReviewSweepScheduleRequest" required: true responses: "201": content: application/json: schema: $ref: "#/components/schemas/ReviewSweepSchedule" description: Schedule created "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "The kind cannot be swept, or the lookback is longer than the\ \ cadence allows" "409": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: This workspace already sweeps that kind of work summary: Start sweeping a kind of work on a cadence tags: - Practice Review Sweep /workspaces/{workspaceSlug}/practices/sweep-schedules/{scheduleId}: delete: description: Removes the instruction. Campaigns it already opened keep their records. operationId: deleteSweepSchedule parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: scheduleId required: true schema: type: string format: uuid responses: "204": description: Schedule removed "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: No such schedule in this workspace summary: Stop sweeping tags: - Practice Review Sweep put: description: "Changes the cadence, the window, or whether the sweep runs at\ \ all." operationId: replaceSweepSchedule parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: scheduleId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateReviewSweepScheduleRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/ReviewSweepSchedule" description: Schedule updated "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: No such schedule in this workspace summary: Replace a sweep schedule's terms tags: - Practice Review Sweep /workspaces/{workspaceSlug}/practices/trace: get: description: "Workspace admins only. Built from the signal ledger, so it includes\ \ work that was never reviewed — which is exactly what a listing derived from\ \ review runs cannot show. Most recently signalled first." operationId: listTracedArtifacts parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: page required: false schema: type: integer format: int32 default: 0 minimum: 0 - in: query name: size required: false schema: type: integer format: int32 default: 25 maximum: 100 minimum: 1 - description: "Restrict to one kind of work, e.g. scm.pull_request" in: query name: artifactKind required: false schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/PagedModelTracedArtifact" description: Paginated artifacts returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Unknown artifact kind or invalid pagination "403": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Workspace administrator access is required summary: List work this workspace recorded something about tags: - Practice review trace /workspaces/{workspaceSlug}/practices/trace/{artifactKind}/{artifactId}: get: description: "Every practice the workspace runs against this kind of work appears,\ \ including the ones that did nothing, each with the recorded reason. Name\ \ a review and every answer is that review's own. A workspace admin may read\ \ any work, with or without a review; anyone else must name a review that\ \ observed them on this work, and reads only the observations about them and\ \ the feedback addressed to them. 404 means nothing about this artifact was\ \ ever recorded here, the named review never ran on it, or the caller may\ \ not read it." operationId: getArtifactTrace parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: "Kind of work, e.g. scm.pull_request" in: path name: artifactKind required: true schema: type: string - description: The artifact's identifier as the ledger stores it in: path name: artifactId required: true schema: type: integer format: int64 - description: "Answer for this review alone: every state, explanation and count\ \ is what this review made of the work. Omit it for every review of the\ \ work at once, which only a workspace admin may." in: query name: reviewId required: false schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/ArtifactTrace" description: Trace returned "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "Nothing recorded about this artifact in this workspace, the\ \ named review never ran on it, or the caller may not read it" summary: Explain what every practice did about one piece of work tags: - Practice review trace /workspaces/{workspaceSlug}/practices/trace/{artifactKind}/{artifactId}/own: get: description: "Counts only observations about the caller and feedback addressed\ \ to them, including when the caller is a workspace admin. The named review\ \ must have observed them on this work. An inaccessible review answers the\ \ same 404 as an absent one." operationId: getOwnArtifactTrace parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: artifactKind required: true schema: type: string - in: path name: artifactId required: true schema: type: integer format: int64 - in: query name: reviewId required: true schema: type: string format: uuid responses: "200": content: application/json: schema: $ref: "#/components/schemas/ArtifactTrace" description: The caller's trace returned "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The caller has no accessible review on this work summary: Explain a named review of the calling developer's own work tags: - Practice review trace /workspaces/{workspaceSlug}/practices/workspace-overview: get: description: "Counts developers, never names them. Every split shows all its\ \ parts, however few developers they count. The splits count every developer's\ \ current standing and take no window." operationId: getPracticesAcrossWorkspace parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticesAcrossWorkspace" description: Practices across the workspace returned summary: "How the workspace's developers split across practice groups and practices,\ \ the reader marked" tags: - Practices Across The Workspace /workspaces/{workspaceSlug}/practices/workspace-overview/tiles: get: description: A middle half shows whenever one or more developers are counted in the window. operationId: getPracticesAcrossWorkspaceTiles parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: window required: true schema: type: string enum: - ALL_TIME - DAYS_30 - DAYS_90 responses: "200": content: application/json: schema: $ref: "#/components/schemas/PracticesAcrossWorkspaceTiles" description: The tiles for the window returned summary: The reader's figures over one window beside the workspace's middle half tags: - Practices Across The Workspace /workspaces/{workspaceSlug}/practices/{practiceSlug}: delete: operationId: deletePractice parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: practiceSlug required: true schema: type: string responses: "204": description: Practice deleted "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice not found summary: Delete a practice definition tags: - Practice Catalog get: operationId: getPractice parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: practiceSlug required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/Practice" description: Practice returned "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice not found summary: Get a practice definition tags: - Practice Catalog patch: operationId: updatePractice parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: practiceSlug required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdatePracticeRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Practice" description: Practice updated "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice or practice group not found summary: Update a practice tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/{practiceSlug}/autonomy: patch: description: "OFF stops the review entirely. HUMAN_APPROVAL runs it and records\ \ every observation, holds feedback on the work for an authorized reviewer,\ \ and still writes the developer's practice pages and the mentor, which are\ \ read on request. AUTOMATIC sends feedback on the work without asking, as\ \ far as this workspace's reach allows. Send a null autonomy to clear the\ \ practice's own setting so it follows its group, and through the group the\ \ workspace default." operationId: setAutonomy parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: practiceSlug required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdatePracticeAutonomyRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Practice" description: Autonomy updated; the response carries the autonomy now in force and where it came from "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: The autonomy cannot be selected because this practice's review settings cannot run an automated review at any autonomy above OFF "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice not found summary: Set how much autonomy the system has over one practice tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/{practiceSlug}/group: put: description: "Moves the practice to the requested group, or to Unassigned when\ \ groupSlug is null" operationId: bindGroup parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: practiceSlug required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/BindPracticeGroupRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Practice" description: Practice moved "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice or group not found summary: Move a practice tags: - Practice Catalog /workspaces/{workspaceSlug}/practices/{practiceSlug}/placement: put: description: Moves the practice and sets its exact position in one atomic write; omit groupSlug for Unassigned operationId: placePractice parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: practiceSlug required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/PlacePracticeRequest" required: true responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/Practice" description: Practice placed; the full updated practice list is returned "400": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: "position is missing, negative, or beyond the destination" "404": content: application/problem+json: schema: $ref: "#/components/schemas/ProblemDetail" description: Practice or group not found summary: Place a practice in the catalog tags: - Practice Catalog /workspaces/{workspaceSlug}/product-feedback: post: operationId: submitWorkspaceProductFeedback parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/FeedbackRequest" required: true responses: "200": description: OK summary: Send product feedback to instance administrators tags: - feedback /workspaces/{workspaceSlug}/product-feedback/surveys: get: operationId: listProductSurveyInvitations parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/SurveyInvitation" description: OK summary: List the open surveys the current account has neither answered nor declined tags: - feedback /workspaces/{workspaceSlug}/product-feedback/surveys/{surveyId}/decline: delete: operationId: undoProductSurveyDecline parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: surveyId required: true schema: type: string format: uuid responses: "200": description: OK summary: Undo a decline; a submitted response is never touched tags: - feedback put: operationId: declineProductSurvey parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: surveyId required: true schema: type: string format: uuid responses: "200": description: OK summary: Decline a survey for the current account tags: - feedback /workspaces/{workspaceSlug}/product-feedback/surveys/{surveyId}/invitation: put: operationId: acknowledgeProductSurveyInvitation parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: surveyId required: true schema: type: string format: uuid responses: "200": description: OK summary: Record that the invitation was shown to the current account tags: - feedback /workspaces/{workspaceSlug}/product-feedback/surveys/{surveyId}/responses: post: operationId: submitProductSurveyResponse parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: surveyId required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/SubmitSurvey" required: true responses: "200": description: OK summary: Submit a survey response once tags: - feedback /workspaces/{workspaceSlug}/public-activity: get: operationId: getWorkspacePublicActivitySettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityWorkspaceSettings" description: OK summary: Get public activity and search indexing settings tags: - workspace patch: operationId: updatePublicActivity parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateWorkspacePublicActivityRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/PublicActivityWorkspaceSettings" description: Workspace updated summary: Turn the public activity page and search indexing on or off tags: - workspace /workspaces/{workspaceSlug}/repositories: delete: operationId: removeRepositoryToMonitor parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: nameWithOwner required: true schema: type: string responses: "200": description: OK summary: Remove a repository from a workspace monitor list tags: - workspace get: operationId: getRepositoriesToMonitor parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: type: string description: Repository list summary: List repositories monitored by a workspace tags: - workspace post: operationId: addRepositoryToMonitor parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: nameWithOwner required: true schema: type: string responses: "200": description: OK summary: Add a repository to a workspace monitor list tags: - workspace /workspaces/{workspaceSlug}/slack/channels: get: operationId: listSlackChannels parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/SlackMonitoredChannel" description: OK summary: List the workspace's allow-listed Slack channels with their consent state tags: - Slack channel activation post: operationId: registerSlackChannel parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/RegisterSlackChannelRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/SlackMonitoredChannel" description: OK summary: Allow-list a Slack channel (lands in PENDING; idempotent on the natural key) tags: - Slack channel activation /workspaces/{workspaceSlug}/slack/channels/candidates: get: operationId: listSlackChannelCandidates parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/SlackChannelCandidate" description: OK summary: List Slack channels available to add to monitoring tags: - Slack channel activation /workspaces/{workspaceSlug}/slack/channels/{slackChannelId}: patch: operationId: updateSlackChannelConsent parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slackChannelId required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateSlackChannelConsentRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/SlackMonitoredChannel" description: OK summary: Transition a Slack channel to a target consent state (activate / pause / resume / revoke) tags: - Slack channel activation /workspaces/{workspaceSlug}/slack/channels/{slackChannelId}/consent-events: get: operationId: listSlackChannelConsentEvents parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: slackChannelId required: true schema: type: string responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/SlackChannelConsentEvent" description: OK summary: The immutable consent-transition audit trail of one Slack channel tags: - Slack channel activation /workspaces/{workspaceSlug}/slack/me/preferences: patch: operationId: updateSlackUserPreferences parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateSlackUserPreferencesRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/SlackUserWorkspacePreferences" description: OK summary: Update current user's Slack workspace preferences tags: - Slack User Preferences /workspaces/{workspaceSlug}/slug: patch: operationId: renameSlug parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/RenameWorkspaceSlugRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Workspace" description: Workspace renamed summary: Rename workspace slug and create redirect tags: - workspace /workspaces/{workspaceSlug}/status: patch: operationId: updateStatus parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateWorkspaceStatusRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Workspace" description: Workspace updated summary: Update workspace lifecycle status tags: - workspace /workspaces/{workspaceSlug}/team: get: description: Returns all teams in the workspace organization operationId: getAllTeams parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/TeamInfo" description: list of teams with their members and permissions summary: List teams tags: - Teams /workspaces/{workspaceSlug}/team/{id}/visibility: post: description: Show or hide a team in workspace activity operationId: updateTeamVisibility parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: the team ID in: path name: id required: true schema: type: integer format: int64 - description: "whether to hide the team (query parameter, fallback)" in: query name: hidden required: false schema: type: boolean requestBody: content: application/json: schema: type: boolean description: "whether to hide the team (body parameter, preferred)" responses: "200": description: "200 OK on success, 404 if team not found" summary: Update team visibility tags: - Teams /workspaces/{workspaceSlug}/team/{teamId}/repositories/{repositoryId}/visibility: post: operationId: updateRepositoryVisibility parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: teamId required: true schema: type: integer format: int64 - in: path name: repositoryId required: true schema: type: integer format: int64 - in: query name: hiddenFromContributions required: false schema: type: boolean requestBody: content: application/json: schema: type: boolean responses: "200": description: OK tags: - Teams /workspaces/{workspaceSlug}/teams/{teamId}/labels/{labelId}: delete: operationId: removeLabelFromTeam parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: teamId required: true schema: type: integer format: int64 - in: path name: labelId required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/TeamInfo" description: OK summary: Remove a repository label from a team tags: - workspace /workspaces/{workspaceSlug}/teams/{teamId}/labels/{repositoryId}/{label}: post: operationId: addLabelToTeam parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: teamId required: true schema: type: integer format: int64 - in: path name: repositoryId required: true schema: type: integer format: int64 - in: path name: label required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/TeamInfo" description: OK summary: Add a repository label to a team tags: - workspace /workspaces/{workspaceSlug}/teams/{teamId}/settings: get: description: Returns the visibility settings for a team in the workspace operationId: getTeamSettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: the team ID in: path name: teamId required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceTeamSettings" description: Team settings returned summary: Get team settings tags: - Team Settings patch: description: Updates the visibility settings for a team in the workspace operationId: updateTeamSettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: the team ID in: path name: teamId required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateTeamSettingsRequest" description: the update request containing the hidden flag required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceTeamSettings" description: Team settings updated "404": content: application/json: schema: $ref: "#/components/schemas/WorkspaceTeamSettings" description: Team not found in workspace summary: Update team settings tags: - Team Settings /workspaces/{workspaceSlug}/teams/{teamId}/settings/label-filters: get: description: Returns all labels configured as filters for a team in the workspace operationId: getLabelFilters parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: the team ID in: path name: teamId required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/LabelInfo" description: Label filters returned summary: Get team label filters tags: - Team Settings /workspaces/{workspaceSlug}/teams/{teamId}/settings/label-filters/{labelId}: delete: description: Removes a label filter from a team in the workspace operationId: removeLabelFilter parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: the team ID in: path name: teamId required: true schema: type: integer format: int64 - description: the label ID to remove as filter in: path name: labelId required: true schema: type: integer format: int64 responses: "204": description: Label filter removed "404": description: Label filter not found summary: Remove label filter tags: - Team Settings post: description: Adds a label as a filter for a team in the workspace operationId: addLabelFilter parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: the team ID in: path name: teamId required: true schema: type: integer format: int64 - description: the label ID to add as filter in: path name: labelId required: true schema: type: integer format: int64 responses: "201": description: Label filter added "404": description: Team or label not found summary: Add label filter tags: - Team Settings /workspaces/{workspaceSlug}/teams/{teamId}/settings/repositories/{repositoryId}: get: description: Returns the contribution visibility settings for a repository in a team operationId: getRepositorySettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: the team ID in: path name: teamId required: true schema: type: integer format: int64 - description: the repository ID in: path name: repositoryId required: true schema: type: integer format: int64 responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceTeamRepositorySettings" description: Repository settings returned summary: Get repository settings tags: - Team Settings patch: description: Updates the contribution visibility settings for a repository in a team operationId: updateRepositorySettings parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - description: the team ID in: path name: teamId required: true schema: type: integer format: int64 - description: the repository ID in: path name: repositoryId required: true schema: type: integer format: int64 requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateRepositorySettingsRequest" description: the update request containing the hiddenFromContributions flag required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/WorkspaceTeamRepositorySettings" description: Repository settings updated "404": content: application/json: schema: $ref: "#/components/schemas/WorkspaceTeamRepositorySettings" description: Team or repository not found summary: Update repository settings tags: - Team Settings /workspaces/{workspaceSlug}/token: patch: operationId: updateToken parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateWorkspaceTokenRequest" required: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Workspace" description: Workspace updated summary: Update workspace Personal Access Token tags: - workspace /workspaces/{workspaceSlug}/user-view/users: get: operationId: listUserViewUsers parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: query name: page required: false schema: type: integer format: int32 default: 0 minimum: 0 - in: query name: size required: false schema: type: integer format: int32 default: 25 maximum: 100 minimum: 1 responses: "200": content: application/json: schema: $ref: "#/components/schemas/PageResponseDTOUserViewUser" description: OK summary: List workspace users and their linked account status tags: - User view /workspaces/{workspaceSlug}/user-view/users/{userId}: get: operationId: getUserViewUser parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" - in: path name: userId required: true schema: type: integer format: int64 - description: "Why the administrator views this user: percent-encoded UTF-8,\ \ 1–500 characters" in: header name: X-User-View-Reason required: true schema: type: string responses: "200": content: application/json: schema: $ref: "#/components/schemas/UserViewUser" description: OK summary: Confirm access to a workspace user tags: - User view /workspaces/{workspaceSlug}/users: get: operationId: getUsersWithTeams parameters: - description: Workspace slug in: path name: workspaceSlug required: true schema: type: string maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" responses: "200": content: application/json: schema: type: array items: $ref: "#/components/schemas/UserTeams" description: OK summary: List workspace users and the teams they belong to tags: - workspace components: schemas: AcceptPracticeReleaseRequest: type: object properties: choices: type: object additionalProperties: type: string enum: - CURRENT - OFFERED required: - choices AccountAiChoice: type: object description: One account-wide answer; model names belong only to workspace-specific views. properties: choice: type: string enum: - NO_AI - IN_HOUSE_ONLY - CLOUD updatedAt: type: string format: date-time AccountAiChoiceRequest: type: object properties: choice: type: string enum: - NO_AI - IN_HOUSE_ONLY - CLOUD required: - choice AccountRef: type: object description: A human-readable account identity. displayName/email are null for deleted accounts. properties: displayName: type: string email: type: string id: type: integer format: int64 required: - id ActivityAction: type: object description: How often one kind of activity happened on a piece of work properties: count: type: integer format: int32 description: How often it was done example: 3 kind: type: string description: What was done enum: - PULL_REQUEST_OPENED - PULL_REQUEST_MERGED - PULL_REQUEST_CLOSED - REVIEW_APPROVED - REVIEW_CHANGES_REQUESTED - REVIEW_COMMENTED - COMMENTED - CODE_COMMENTED - ISSUE_OPENED - ISSUE_CLOSED required: - count - kind ActivityBreakdown: type: object properties: approvals: type: integer format: int32 changeRequests: type: integer format: int32 codeComments: type: integer format: int32 commentReviews: type: integer format: int32 discussionComments: type: integer format: int32 issuesClosed: type: integer format: int32 pullRequestsClosed: type: integer format: int32 required: - approvals - changeRequests - codeComments - commentReviews - discussionComments - issuesClosed - pullRequestsClosed ActivityCounts: type: object properties: activeWeeks: type: integer format: int64 comments: type: integer format: int64 contributions: type: integer format: int64 issuesOpened: type: integer format: int64 peopleHelped: type: integer format: int64 pullRequestsMerged: type: integer format: int64 pullRequestsOpened: type: integer format: int64 pullRequestsReviewed: type: integer format: int64 required: - activeWeeks - comments - contributions - issuesOpened - peopleHelped - pullRequestsMerged - pullRequestsOpened - pullRequestsReviewed ActivityCoverage: type: object description: "Completion comes from backfill checkpoints, not the presence of\ \ ledger events." properties: completeRepositories: type: integer format: int64 since: type: string format: date-time totalRepositories: type: integer format: int64 required: - completeRepositories - totalRepositories ActivityHighlights: type: object description: Identifiers refer only to the people in the same response. properties: firstContributors: type: array items: type: integer format: int64 mostPeopleHelped: type: array items: type: integer format: int64 required: - firstContributors - mostPeopleHelped ActivityPeople: type: object properties: automation: type: array items: $ref: "#/components/schemas/ActivityPerson" coverage: $ref: "#/components/schemas/ActivityCoverage" from: type: string format: date-time highlights: $ref: "#/components/schemas/ActivityHighlights" people: type: array items: $ref: "#/components/schemas/ActivityPerson" repositories: type: array items: $ref: "#/components/schemas/ActivityRepository" teams: type: array items: $ref: "#/components/schemas/ActivityTeam" to: type: string format: date-time required: - automation - coverage - from - highlights - people - repositories - teams - to ActivityPerson: type: object properties: counts: $ref: "#/components/schemas/ActivityCounts" firstContributionAt: type: string format: date-time kind: type: string enum: - PERSON - BOT - AUTOMATION person: $ref: "#/components/schemas/UserInfo" weeks: type: array items: $ref: "#/components/schemas/ActivitySparklineWeek" required: - counts - kind - person - weeks ActivityPersonDetail: type: object properties: breakdown: $ref: "#/components/schemas/ActivityBreakdown" counts: $ref: "#/components/schemas/ActivityCounts" firstContributionAt: type: string format: date-time from: type: string format: date-time kind: type: string enum: - PERSON - BOT - AUTOMATION person: $ref: "#/components/schemas/UserInfo" repositories: type: array items: $ref: "#/components/schemas/ActivityRepositoryCounts" to: type: string format: date-time weeks: type: array items: $ref: "#/components/schemas/ActivityWeek" required: - breakdown - counts - from - kind - person - repositories - to - weeks ActivityRepository: type: object description: The full provider path avoids collisions between repositories with the same name. properties: id: type: integer format: int64 key: type: string name: type: string required: - id - key - name ActivityRepositoryCounts: type: object properties: breakdown: $ref: "#/components/schemas/ActivityBreakdown" counts: $ref: "#/components/schemas/ActivityCounts" repository: $ref: "#/components/schemas/ActivityRepository" required: - breakdown - counts - repository ActivitySparklineWeek: type: object properties: contributions: type: integer format: int64 start: type: string format: date-time required: - contributions - start ActivityTeam: type: object properties: id: type: integer format: int64 key: type: string name: type: string parentId: type: integer format: int64 required: - id - key - name ActivityWeek: type: object properties: breakdown: $ref: "#/components/schemas/ActivityBreakdown" counts: $ref: "#/components/schemas/ActivityCounts" start: type: string format: date-time required: - breakdown - counts - start ActivityWork: type: object description: The activity on one pull request or issue in a time range properties: actions: type: array description: "Each kind of activity that happened on it, in a fixed order\ \ of kinds" items: $ref: "#/components/schemas/ActivityAction" id: type: string description: "Identifier of the group: work:,\ \ or event: for activity whose pull request or issue\ \ is not known" lastOccurredAt: type: string format: date-time description: When the latest of this activity happened people: type: array description: "Everyone this activity counts for, by name" items: $ref: "#/components/schemas/UserInfo" work: $ref: "#/components/schemas/WorkItem" description: "The pull request or issue; null when it, or the review or\ \ comment the activity was, is no longer known or was deleted upstream" required: - actions - id - lastOccurredAt - people ActivityWorkPage: type: object description: "One page of activity grouped by the pull request or issue it happened\ \ on, latest first" properties: content: type: array description: "The work on this page, by its latest activity, newest first" items: $ref: "#/components/schemas/ActivityWork" nextCursor: type: string description: Opaque cursor that fetches the next page when passed back as cursor; absent on the last page required: - content AdminAccountView: type: object properties: appRole: type: string enum: - USER - APP_ADMIN displayName: type: string id: type: integer format: int64 primaryEmail: type: string status: type: string enum: - ACTIVE - SUSPENDED - DELETING - DELETED required: - appRole - status AdminLlmUsageReport: type: object description: "Instance-admin per-workspace month rollup (metadata only, no tenant\ \ content)" properties: fx: $ref: "#/components/schemas/FxRateInfo" description: Display-only conversion when the instance has a display currency. Absent = show USD only. Applies to every USD amount in this response. month: type: string description: "Calendar month (UTC), ISO yyyy-MM" example: 2026-07 workspaces: type: array description: "One row per workspace, including workspaces with no ledger\ \ activity this month" items: $ref: "#/components/schemas/AdminWorkspaceLlmUsage" required: - month - workspaces AdminWorkspaceLlmUsage: type: object description: "One workspace's month of spend, as an instance admin sees it" properties: displayName: type: string events: type: integer format: int64 description: "Ledger events (jobs / mentor turns) this month, either purse" instanceBudgetVerdict: type: string description: "Whether shared-model spend is within the instance cap, has\ \ reached it, or cannot be confirmed because some shared-model usage has\ \ no price set." enum: - WITHIN - EXHAUSTED - UNVERIFIABLE instanceMonthlyBudgetUsd: type: number format: decimal description: Monthly cap in USD on this workspace's spend on shared (instance) models — the money this instance pays for; null = uncapped. Yours to set. instancePaused: type: boolean description: "Whether work on SHARED models is paused for this workspace\ \ right now (current month only) — authoritative, mirroring the live gate." instanceTotalCostUsd: type: number format: decimal description: "This month's confirmed spend on shared (instance) models,\ \ in USD — compared against instanceMonthlyBudgetUsd." ownProviderBudgetVerdict: type: string description: The same verdict for the workspace's own-provider spend against its own cap. enum: - WITHIN - EXHAUSTED - UNVERIFIABLE ownProviderMonthlyBudgetUsd: type: number format: decimal description: "The workspace's own cap in USD on its own-provider spend;\ \ null = uncapped. Read-only here — it governs the workspace's money,\ \ so only its own admins may change it." ownProviderPaused: type: boolean description: Whether work on the workspace's OWN provider is paused right now. ownProviderTotalCostUsd: type: number format: decimal description: "This month's confirmed spend on the workspace's own connected\ \ provider(s), in USD — compared against ownProviderMonthlyBudgetUsd." workspaceSlug: type: string description: "Addresses the workspace everywhere else in the API, including\ \ its cap" required: - displayName - events - instanceBudgetVerdict - instancePaused - instanceTotalCostUsd - ownProviderBudgetVerdict - ownProviderPaused - ownProviderTotalCostUsd - workspaceSlug AdminWorkspaceView: type: object description: Metadata-only workspace summary for the instance-admin overview properties: accountLogin: type: string createdAt: type: string format: date-time displayName: type: string id: type: integer format: int64 memberCount: type: integer format: int64 ownerLogin: type: string providerType: type: string enum: - GITHUB - GITLAB - SLACK - OUTLINE status: type: string enum: - ACTIVE - SUSPENDED - PURGED workspaceSlug: type: string required: - accountLogin - createdAt - displayName - id - memberCount - status - workspaceSlug AgentBinding: type: object description: A workspace's agent binding for one purpose properties: allowInternet: type: boolean dataHandlingTier: type: string enum: - IN_HOUSE - CLOUD - UNDECLARED enabled: type: boolean instanceModelId: type: integer format: int64 maxConcurrentJobs: type: integer format: int32 purpose: type: string enum: - PRACTICE_REVIEW - MENTOR ready: type: boolean description: True when the bound model is available to run right now timeoutSeconds: type: integer format: int32 workspaceModelId: type: integer format: int64 required: - dataHandlingTier - enabled - purpose - ready AgentBindingRequest: type: object description: Bind a model and execution limits to an agent purpose properties: allowInternet: type: boolean description: Whether the sandbox may reach the public internet enabled: type: boolean description: Whether this purpose is active (paused when false) instanceModelId: type: integer format: int64 description: Shared (instance-catalog) model id to run this purpose on maxConcurrentJobs: type: integer format: int32 description: Maximum concurrent runs for this purpose minimum: 1 timeoutSeconds: type: integer format: int32 description: Per-run timeout in seconds (30–10800; three hours is the longest a single run may take) maximum: 10800 minimum: 30 workspaceModelId: type: integer format: int64 description: Workspace-owned model id to run this purpose on AgentJob: type: object description: Agent job execution record (job_token intentionally omitted) properties: answeredPractices: type: array description: Ready practices this review did not ask because a completed review had already answered them on the same code; available on review detail after evidence capture. Empty when every ready practice was asked. items: $ref: "#/components/schemas/AnsweredPractice" availableAt: type: string format: date-time description: "When this job becomes eligible to be claimed. In the future\ \ while the job is waiting — on a retry backoff, or on a hold. Read together\ \ with holdReason: a QUEUED job with availableAt in the future is waiting,\ \ not starved for workers." completedAt: type: string format: date-time description: Timestamp when the job completed configSnapshot: description: Frozen agent config at submit time (an INSTANCE-scoped connection's baseUrl is redacted to scheme://host; only a WORKSPACE-scoped connection's baseUrl is left intact) coveringJobId: type: string format: uuid description: The newer review that replaced this one; set only when reviewOutcome is SUPERSEDED createdAt: type: string format: date-time description: Timestamp when the job was created deliveryCommentId: type: string description: Git provider comment/note ID for posted feedback deliveryStatus: type: string description: "Result-processing status: null = not applicable, PENDING =\ \ awaiting processing, DELIVERED = processing finished, FAILED = processing\ \ error. Processing may include delivery; this status alone does not establish\ \ feedback publication." enum: - PENDING - DELIVERED - FAILED errorMessage: type: string description: Human-readable error message exitCode: type: integer format: int32 description: Container exit code generatedPaths: $ref: "#/components/schemas/GeneratedPathReview" description: Frozen generated-path policy and changed paths marked generated; available on review detail after evidence capture holdReason: type: string description: "Why a QUEUED job is waiting rather than eligible, when the\ \ reason is one an admin can undo. BUDGET = the payer is over its monthly\ \ LLM cap and the job resumes by itself once the cap is raised or the\ \ month rolls over. Absent means no such hold — a future availableAt is\ \ then an ordinary retry backoff." id: type: string format: uuid description: Job ID jobType: type: string description: Job type enum: - PULL_REQUEST_REVIEW - ISSUE_REVIEW - CONVERSATION_REVIEW - DOCUMENT_REVIEW llmCacheReadTokens: type: integer format: int32 description: Tokens read from prompt cache llmCacheWriteTokens: type: integer format: int32 description: Tokens written to prompt cache llmModel: type: string description: "LLM model used (e.g. gpt-5.4-mini, openai/gpt-oss-120b)" llmModelVersion: type: string description: Model version/snapshot date (e.g. 2026-03-17). Only jobs from before the model catalog carry one; absent on everything newer. llmTotalCalls: type: integer format: int32 description: Total LLM API calls (steps) during execution llmTotalInputTokens: type: integer format: int32 description: Total input tokens consumed llmTotalOutputTokens: type: integer format: int32 description: Total output tokens generated llmTotalReasoningTokens: type: integer format: int32 description: Total reasoning/thinking tokens metadata: description: Job metadata (routing/display info) model: type: string description: "Upstream model this job was admitted on, frozen at submit\ \ time (e.g. gpt-5.4-mini). Available from submission, unlike llmModel,\ \ which the runner reports only once the job has run." output: description: Job output (agent results) retryCount: type: integer format: int32 description: Number of retry attempts reviewOutcome: type: string description: "Why a COMPLETED run produced the observations it did. INSUFFICIENT_EVIDENCE\ \ means no model ran because required evidence was missing, unreadable,\ \ stale, or unauthorized — so no observations means nothing was assessed,\ \ not that nothing was wrong. COALESCED means no model ran because a completed\ \ review had already answered every ready practice on exactly the same\ \ code — its answers are listed in answeredPractices, and this run assessed\ \ nothing anew. SUPERSEDED means the waiting attempt was replaced by an\ \ admitted newer review of the same author's current work, named in coveringJobId,\ \ which carries this review's practices and may still be waiting or running;\ \ the replacement makes no additional assessment, and earlier attempt\ \ history remains. REVIEWED means the model ran against sufficient evidence." enum: - REVIEWED - INSUFFICIENT_EVIDENCE - COALESCED - SUPERSEDED startedAt: type: string format: date-time description: Timestamp when the job started running status: type: string description: Current job status enum: - QUEUED - RUNNING - COMPLETED - FAILED - TIMED_OUT - CANCELLED target: $ref: "#/components/schemas/ReviewRunTarget" description: Work item reviewed by this job required: - availableAt - configSnapshot - createdAt - id - jobType - retryCount - reviewOutcome - status - target Answer: type: object description: One answer; exactly the field matching the question's type is set. properties: choices: type: array items: type: string maxLength: 200 minLength: 0 maxItems: 20 minItems: 0 questionId: type: string maxLength: 80 minLength: 0 rating: type: integer format: int32 maximum: 10 minimum: 0 text: type: string maxLength: 4000 minLength: 0 required: - questionId AnsweredPractice: type: object description: "A ready practice this review did not ask, because a completed\ \ review had already answered it on exactly the same code. Its observation\ \ belongs to that review; this review recorded none for it." properties: practiceSlug: type: string description: The practice left out reviewId: type: string format: uuid description: The completed review whose observation answers it revisionId: type: integer format: int64 description: The practice revision the earlier answer was made under required: - practiceSlug - reviewId - revisionId ArtifactTrace: type: object description: "Every practice's answer for one artifact, and the occurrences\ \ those answers rest on" properties: artifactId: type: integer format: int64 artifactKind: type: string practices: type: array description: "Every practice this workspace runs against this kind of work,\ \ the ones with something to report first, then the rest; ties broken\ \ by practice name" items: $ref: "#/components/schemas/PracticeTraceEntry" reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" description: "The work as every surface names it: its provider, the label\ \ the provider writes (\"#1423\", \"!1423\"), its title, where it sits\ \ and where to open it; the link is absent for deleted work" signals: type: array description: "Everything recorded about this artifact, oldest first" items: $ref: "#/components/schemas/TracedSignal" required: - artifactId - artifactKind - practices - reviewedWork - signals AssignRoleRequest: type: object description: Request to assign or update a user's role in a workspace properties: role: type: string description: "New role to assign (OWNER, ADMIN, MEMBER)" enum: - OWNER - ADMIN - MEMBER userId: type: integer format: int64 description: User ID of the member to update required: - role - userId AuthEventView: type: object description: "One audit row, flattened for the admin viewer." properties: account: $ref: "#/components/schemas/AccountRef" accountId: type: integer format: int64 actingAccountId: type: integer format: int64 actor: $ref: "#/components/schemas/AccountRef" details: type: string elevatedViaInstanceAdmin: type: boolean eventType: type: string failureReason: type: string id: type: integer format: int64 ipAddress: type: string occurredAt: type: string format: date-time result: type: string userAgent: type: string viewedUserId: type: integer format: int64 workspaceId: type: integer format: int64 required: - elevatedViaInstanceAdmin - eventType - id - occurredAt - result AutonomyAssignment: type: object description: "The autonomy in force here, whether it was set here or inherited,\ \ and the level that decided it" properties: effective: type: string description: The autonomy actually in force enum: - "OFF" - HUMAN_APPROVAL - AUTOMATIC inherited: type: boolean description: Whether autonomy is inherited override: type: string description: "The local override, or null when autonomy is inherited" enum: - "OFF" - HUMAN_APPROVAL - AUTOMATIC source: type: string description: Which level decided the effective autonomy enum: - PRACTICE - GROUP - WORKSPACE required: - effective - inherited - source AutonomyRollup: type: object description: "Practice counts per autonomy state, for the workspace and each\ \ group" properties: counts: type: object additionalProperties: type: integer format: int32 description: Practice count per effective autonomy across the workspace groups: type: array description: "The same counts per group, in catalogue order" items: $ref: "#/components/schemas/GroupAutonomyRollup" workspaceDefault: $ref: "#/components/schemas/AutonomyAssignment" description: The workspace-level decision every group and practice falls back to required: - counts - groups - workspaceDefault AvailableLlmModel: type: object description: A model available for this workspace to bind a Task to properties: brand: type: string description: Model brand declared by an admin; display only enum: - OPENAI - ANTHROPIC - GEMINI - GEMMA - META - MISTRAL - QWEN - DEEPSEEK - XAI - COHERE - Z_AI - MOONSHOT connectionDisplayName: type: string description: Owning connection's display name dataHandlingTier: type: string description: Data-handling tier derived from the admin's declared facts enum: - IN_HOUSE - CLOUD - UNDECLARED displayName: type: string description: Human-readable name id: type: integer format: int64 description: "Model id, unique within its scope" per1mCacheReadUsd: type: number format: decimal description: Cache-read rate per 1M tokens (USD) per1mCacheWriteUsd: type: number format: decimal description: Cache-write rate per 1M tokens (USD) per1mInputUsd: type: number format: decimal description: Input rate per 1M tokens (USD) per1mOutputUsd: type: number format: decimal description: Output rate per 1M tokens (USD) pricingMode: type: string description: Pricing mode enum: - PRICED - NO_CHARGE - UNPRICED reasoningEffort: type: string description: "Reasoning effort requested of the model; null sends none,\ \ the provider's default applies" enum: - NONE - MINIMAL - LOW - MEDIUM - HIGH - XHIGH - MAX scope: type: string description: SHARED (instance catalog) or WORKSPACE (your own provider) enum: - SHARED - WORKSPACE required: - connectionDisplayName - dataHandlingTier - displayName - id - pricingMode - scope BackfillSummary: type: object description: Connection-level backfill rollup properties: percent: type: integer format: int32 description: "0-100 completion estimate, if computable" state: type: string description: Integration-defined backfill state string required: - state BindPracticeGroupRequest: type: object additionalProperties: false description: Request to move a practice to a group or Unassigned properties: groupSlug: type: - string - "null" description: Destination group slug; omit or set to null for Unassigned example: review-ready-work CatalogAdoptionGroup: type: object properties: definition: $ref: "#/components/schemas/CuratedGroupRequest" disposition: type: string enum: - UNASSIGNED - REUSE_EXISTING_GROUP - CREATE_CATALOG_GROUP slug: type: string required: - disposition CatalogEntryStatus: type: object properties: changeKind: type: string enum: - NONE - WORDING - PRESENTATION - REVIEW etag: type: string description: Strong entity tag to send in If-Match when updating this entry offered: type: boolean state: type: string enum: - FROM_HEPHAESTUS - EDITED_HERE - UPDATE_WAITING - YOURS - NO_LONGER_SHIPPED required: - changeKind - etag - offered - state CatalogGroupAdoptionPreview: type: object properties: actions: type: array items: $ref: "#/components/schemas/CatalogGroupPracticeAction" definition: $ref: "#/components/schemas/CuratedGroupRequest" disposition: type: string enum: - UNASSIGNED - REUSE_EXISTING_GROUP - CREATE_CATALOG_GROUP etag: type: string practices: type: array items: $ref: "#/components/schemas/CatalogPracticePreview" slug: type: string required: - actions - definition - disposition - etag - practices - slug CatalogGroupAdoptionResult: type: object properties: added: type: array items: $ref: "#/components/schemas/Practice" moved: type: array items: $ref: "#/components/schemas/Practice" required: - added - moved CatalogGroupPracticeAction: type: object properties: action: type: string enum: - ADD - MOVE_TO_GROUP - KEEP - BLOCKED slug: type: string required: - action - slug CatalogOrigin: type: object description: The catalog entry a workspace copy came from and whether it differs now properties: link: type: string enum: - IN_SYNC - LOCALLY_EDITED - UPDATE_AVAILABLE - DECLINED slug: type: string description: Slug of the catalog entry this copy was made from sourceOffered: type: boolean description: Whether new workspaces receive the source entry required: - link - slug - sourceOffered CatalogPracticePreview: type: object properties: availability: type: string enum: - AVAILABLE - ADOPTED - SLUG_CONFLICT definition: $ref: "#/components/schemas/CuratedPracticeDefinition" etag: type: string group: $ref: "#/components/schemas/CatalogAdoptionGroup" initialAutonomy: type: string enum: - "OFF" - HUMAN_APPROVAL - AUTOMATIC slug: type: string sourceReviewRuleFingerprint: type: string required: - availability - definition - etag - group - initialAutonomy - slug - sourceReviewRuleFingerprint CatalogPracticeSummary: type: object properties: artifactKind: type: string automatedReviewValidation: $ref: "#/components/schemas/PracticeAutomatedReviewValidation" availability: type: string enum: - AVAILABLE - ADOPTED - SLUG_CONFLICT groupName: type: string groupSlug: type: string name: type: string slug: type: string whyItMatters: type: string description: "the practice's rationale, so a row is triageable without opening\ \ it" required: - artifactKind - automatedReviewValidation - availability - name - slug ChatMessage: type: object description: Mentor chat message in AI SDK UIMessage shape. properties: createdAt: type: string format: date-time id: type: string format: uuid metadata: type: object additionalProperties: {} description: "Per-turn metadata: status, model, costUsd, usage, …" parentMessageId: type: string format: uuid parts: type: array items: description: AI SDK UIMessage part (text / data-observation). role: type: string ChatMessageVote: type: object description: User vote on a mentor assistant message. properties: isUpvoted: type: boolean messageId: type: string format: uuid updatedAt: type: string format: date-time ChatMessageVoteRequest: type: object description: Upsert a vote on a mentor assistant message properties: isUpvoted: type: boolean description: "true = upvote (helpful), false = downvote" required: - isUpvoted ChatThreadDetail: type: object description: Mentor chat thread with all messages and the owner's votes on them. properties: createdAt: type: string format: date-time id: type: string format: uuid messages: type: array items: $ref: "#/components/schemas/ChatMessage" title: type: string votes: type: object additionalProperties: type: boolean ChatThreadSummary: type: object description: Mentor chat thread summary (no messages). properties: createdAt: type: string format: date-time id: type: string format: uuid title: type: string required: - createdAt - id ClientRefreshRequest: type: object properties: refreshToken: type: string pattern: "^[A-Za-z0-9_-]{43}$" required: - refreshToken ClientSessionTokens: type: object properties: accessToken: type: string accessTokenExpiresAt: type: string format: date-time refreshToken: type: string sessionExpiresAt: type: string format: date-time required: - accessToken - accessTokenExpiresAt - refreshToken - sessionExpiresAt ClientSignInConfiguration: type: object properties: registered: type: boolean required: - registered ClientTokenRequest: type: object properties: clientId: type: string pattern: "^[a-p]{32}$" code: type: string pattern: "^[A-Za-z0-9_-]{43}$" codeVerifier: type: string pattern: "^[A-Za-z0-9._~-]{43,128}$" redirectUri: type: string maxLength: 200 minLength: 0 required: - clientId - code - codeVerifier - redirectUri ConfigAuditActorRef: type: object description: |- A human-readable actor identity on an audit row. Resolved at read time, so an erased account degrades here without the trail being rewritten: AccountPurger clears the email, replaces the display name with a placeholder, and nulls the row's actor references.

Named distinctly from the auth trail's own AccountRefDTO: the OpenAPI schema key is the simple name minus the DTO suffix, so two AccountRefDTO records would collide and one would be silently dropped from the spec. properties: displayName: type: string email: type: string id: type: integer format: int64 required: - id ConfigAuditEntryView: type: object description: "One audit row, flattened for a viewer. Crosses the module boundary,\ \ so it carries no entity." properties: actingAccountId: type: integer format: int64 actingActor: $ref: "#/components/schemas/ConfigAuditActorRef" description: "resolved impersonator, present only for {@link ConfigAuditActorKind#IMPERSONATED\ \ ConfigAuditActorKind#IMPERSONATED}" action: type: string enum: - CREATED - UPDATED - DELETED actor: $ref: "#/components/schemas/ConfigAuditActorRef" description: |- resolved identity of actorAccountId; null for SYSTEM rows or once the account is gone. Read together with actorKind — that is what keeps "a system did this" distinct from "we no longer know who did this". actorAccountId: type: integer format: int64 actorKind: type: string enum: - USER - SYSTEM - IMPERSONATED changedKeys: type: array description: dot-paths that differ between oldValue and newValue items: type: string elevatedViaInstanceAdmin: type: boolean description: whether the actor reached this workspace by instance-admin elevation entityId: type: string entityType: type: string enum: - PRACTICE_REVIEW_SETTINGS - AGENT_BINDING - AGENT_CONFIG - AI_CONFIG_BINDING - WORKSPACE_ROLE - ACTIVITY_AUTOMATION - WORKSPACE_FEATURES - WORKSPACE_STATUS - WORKSPACE_TOKEN - WORKSPACE_VISIBILITY - PRACTICE_ACTIVE - PRACTICE_USAGE - PRACTICE_DEFINITION - PRACTICE_GROUP - CURATED_PRACTICE - CURATED_PRACTICE_GROUP - WORKSPACE_INSTANCE_LLM_BUDGET - WORKSPACE_OWN_PROVIDER_LLM_BUDGET - WORKSPACE_LLM_BUDGET - WORKSPACE_BYO_LLM_BUDGET - REVIEW_BACKFILL_RUN - REVIEW_SWEEP_SCHEDULE - WORKSPACE_LLM_CONNECTION - WORKSPACE_LLM_MODEL id: type: integer format: int64 newValue: type: string occurredAt: type: string format: date-time oldValue: type: string workspaceId: type: integer format: int64 required: - elevatedViaInstanceAdmin ConfigurationFact: type: object properties: documentationUrl: type: string explanation: type: string id: type: string requirement: type: string enum: - REQUIRED - RECOMMENDED - OPTIONAL roles: type: array items: type: string enum: - SERVER - WORKER - WEBHOOK status: type: string enum: - SATISFIED - ACTION_REQUIRED - NOT_CONFIGURED - NOT_APPLICABLE subject: type: string required: - documentationUrl - explanation - id - requirement - roles - status - subject ConnectionAuditEntry: type: object description: |- Audit-log entry returned by GET /workspaces/{workspaceSlug/connections/{id}/audit}.

Lean projection of {@link ConnectionAudit ConnectionAudit} — the entity carries a back-reference to Connection that this DTO omits. properties: actorAccountId: type: integer format: int64 actorKind: type: string actorRef: type: string correlationId: type: string eventType: type: string fromState: type: string enum: - PENDING - ACTIVE - SUSPENDED - UNINSTALLED occurredAt: type: string format: date-time toState: type: string enum: - PENDING - ACTIVE - SUSPENDED - UNINSTALLED ConnectionDetail: type: object description: |- Detailed view of a single Connection — extends {@link ConnectionSummaryDTO ConnectionSummaryDTO} with the sealed config serialized to a free-form JSON object (Map<String, Object> → type: object, additionalProperties: true in the spec, so it round-trips through client codegen). NEVER carries credentials: the encrypted credential blob stays inside the entity, and every secret-bearing key of the config itself is stripped by redactSensitive before serialization.

Why redact here and not with @JsonIgnore on the record component? The very same ObjectMapper bean serializes ConnectionConfig into the JSONB connection.config column (Hibernate's json_format_mapper is wired to it in HibernateJacksonFormatMapperConfig). Annotating the component would therefore drop the secret on write and destroy the stored value — the API-boundary filter below is the only place the two concerns can be separated.

Mirroring the summary fields (rather than embedding the summary record) keeps the JSON shape flat — the API consumer sees one record, not a nested summary object. properties: attentionProblem: type: string enum: - CREDENTIAL_EXPIRING - CREDENTIAL_REVOKED - PROVIDER_SUSPENDED capabilities: type: array items: type: string enum: - WEBHOOK_INGEST - TOKEN_REFRESH - FEEDBACK_DELIVERY - INLINE_FEEDBACK - APPROVAL_WORKFLOW - SCOPE_CHANGES uniqueItems: true config: type: object additionalProperties: {} createdAt: type: string format: date-time credentialsUnreadableSince: type: string format: date-time displayName: type: string family: type: string enum: - SCM - MESSAGING - DOCUMENTATION id: type: integer format: int64 instanceKey: type: string kind: type: string enum: - GITHUB - GITLAB - SLACK - OUTLINE state: type: string enum: - PENDING - ACTIVE - SUSPENDED - UNINSTALLED stateReason: type: string tokenExpiresAt: type: string format: date tokenExpiryCheckedAt: type: string format: date-time updatedAt: type: string format: date-time ConnectionSummary: type: object description: |- Wire shape returned by the GET /workspaces/{workspaceSlug/connections} list + by lifecycle endpoints (suspend, reactivate). Lightweight — no config, no credentials, no audit. Capabilities are looked up from the per-kind manifest at response build time so adding/removing a capability needs no DB migration. properties: capabilities: type: array items: type: string enum: - WEBHOOK_INGEST - TOKEN_REFRESH - FEEDBACK_DELIVERY - INLINE_FEEDBACK - APPROVAL_WORKFLOW - SCOPE_CHANGES uniqueItems: true createdAt: type: string format: date-time credentialsUnreadableSince: type: string format: date-time displayName: type: string family: type: string enum: - SCM - MESSAGING - DOCUMENTATION id: type: integer format: int64 instanceKey: type: string kind: type: string enum: - GITHUB - GITLAB - SLACK - OUTLINE state: type: string enum: - PENDING - ACTIVE - SUSPENDED - UNINSTALLED stateReason: type: string updatedAt: type: string format: date-time ConnectionSyncStatus: type: object description: Unified sync-observability status for one connection properties: activeJob: $ref: "#/components/schemas/SyncJob" description: "Currently PENDING/RUNNING job, if any" backfill: $ref: "#/components/schemas/BackfillSummary" description: "Connection-level backfill rollup, if applicable" backfillSupported: type: boolean description: "Whether this kind's runner offers an explicitly triggerable\ \ backfill pass. Reflects the vendor capability only — the scheduled-backfill\ \ flag does not gate it, so a manual backfill stays available while the\ \ automatic cycle is administratively paused." connectionId: type: integer format: int64 description: Connection id connectionState: type: string description: Raw connection lifecycle state enum: - PENDING - ACTIVE - SUSPENDED - UNINSTALLED health: type: string description: Derived health enum: - PENDING - HEALTHY - DEGRADED - FAILED - SUSPENDED kind: type: string description: Integration kind enum: - GITHUB - GITLAB - SLACK - OUTLINE lastEventProcessedAt: type: string format: date-time description: "When the last inbound webhook/event was processed for this\ \ connection, if any" lastJob: $ref: "#/components/schemas/SyncJob" description: "Most recently finished job, if any" lastSuccessfulSyncAt: type: string format: date-time description: Most recent successful job's finish time nextScheduledSyncAt: type: string format: date-time description: When the next periodic reconciliation is expected rateLimit: $ref: "#/components/schemas/RateLimitSnapshot" description: "Current rate-limit budget, if known" resourceCounts: $ref: "#/components/schemas/ResourceCounts" description: Resource-level rollup syncIntervalSeconds: type: integer format: int64 description: "The periodic reconciliation's cadence in seconds, when the\ \ schedule has a regular one. This is what makes a resource's lastSyncedAt\ \ judgeable: \"synced 4h ago\" is only stale if the cadence is hourly,\ \ and a client cannot know that without this. Null when the schedule is\ \ irregular or unparseable — clients must then decline to judge staleness\ \ rather than assume a default, exactly as the server's own stale rollup\ \ does." webhookRegistered: type: boolean description: Whether the vendor webhook registration is present; null if not applicable/unknown required: - backfillSupported - connectionId - connectionState - health - kind - resourceCounts ConsentStatus: type: object properties: completed: type: boolean noticeVersion: type: string description: Version of the first-login wording the client must be rendering participateInResearch: type: boolean researchOrganization: type: string description: "Organization that runs the optional research program, or null\ \ when this instance runs none" required: - completed - noticeVersion - participateInResearch Contributor: type: object description: Information about a contributor to the Hephaestus project properties: avatarUrl: type: string description: URL to the contributor's avatar image contributions: type: integer format: int32 description: Number of contributions to the project example: 42 htmlUrl: type: string description: URL to the contributor's GitHub profile id: type: integer format: int64 description: GitHub user ID login: type: string description: GitHub username name: type: string description: Display name of the contributor required: - avatarUrl - htmlUrl - id - login - name CreateCuratedGroupRequest: type: object description: Request to add a group to the instance catalog properties: definition: $ref: "#/components/schemas/CuratedGroupRequest" slug: type: string example: reviewing-work maxLength: 64 minLength: 3 pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$" required: - definition - slug CreateCuratedPracticeRequest: type: object additionalProperties: false description: Request to add a practice to the instance catalog properties: definition: $ref: "#/components/schemas/CuratedPracticeRequest" slug: type: string example: pr-description-quality maxLength: 64 minLength: 3 pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$" required: - definition - slug CreateLlmConnectionRequest: type: object description: Create an instance LLM provider connection properties: apiKey: type: string description: API key (write-only; never returned) apiProtocol: type: string description: Wire protocol example: openai-responses minLength: 1 pattern: openai-completions|openai-responses authMode: type: string description: Credential shape (default BEARER) enum: - BEARER - API_KEY baseUrl: type: string description: Provider base URL maxLength: 2048 minLength: 0 connectionPlatform: type: string description: Admin-declared connection platform; null when not declared enum: - LOGOS - VLLM - OLLAMA - AZURE - AWS_BEDROCK - GOOGLE_VERTEX - OPENAI - GOOGLE_AI_STUDIO - ALIBABA_CLOUD - GROQ - FIREWORKS - TOGETHER_AI - DEEPINFRA - NEBIUS - OPENROUTER - CLOUDFLARE_AI_GATEWAY - VERCEL_AI_GATEWAY displayName: type: string description: Human-readable name maxLength: 128 minLength: 0 enabled: type: boolean description: Whether the connection is enabled (default false) slug: type: string description: Optional internal slug; generated from displayName when omitted maxLength: 63 minLength: 0 required: - apiProtocol - baseUrl - displayName CreateLlmModelRequest: type: object description: Create a model on an instance LLM connection properties: brand: type: string description: Model brand declared by an admin; display only enum: - OPENAI - ANTHROPIC - GEMINI - GEMMA - META - MISTRAL - QWEN - DEEPSEEK - XAI - COHERE - Z_AI - MOONSHOT contextWindow: type: integer format: int32 description: Context window in tokens minimum: 1 dataHandlingNote: type: string description: "Admin-only note: region, agreement, renewal date" maxLength: 200 minLength: 0 displayName: type: string description: Human-readable name maxLength: 128 minLength: 0 enabled: type: boolean description: Whether the model is active (default false) maxOutputTokens: type: integer format: int32 description: Maximum output tokens minimum: 1 operatedBy: type: string description: Who operates the systems the work is sent to; omit to leave the model undeclared enum: - OWN_ORGANISATION - PROVIDER reasoningEffort: type: string description: "Reasoning effort to request; null sends none, so the provider's\ \ own default applies" enum: - NONE - MINIMAL - LOW - MEDIUM - HIGH - XHIGH - MAX slug: type: string description: Optional internal slug; generated from displayName when omitted maxLength: 63 minLength: 0 upstreamModelId: type: string description: Upstream provider model id maxLength: 256 minLength: 0 required: - displayName - upstreamModelId CreateLoginProviderRequest: type: object properties: baseUrl: type: string description: Instance base URL (GitLab only; GitHub is always github.com) example: https://gitlab.example.com clientId: type: string minLength: 1 clientSecret: type: string description: "OAuth client secret; sealed at rest, never returned" minLength: 1 displayName: type: string description: Label shown on the login button; defaults to the registrationId registrationId: type: string description: Stable id used in the OAuth callback path and identity resolution example: gitlab-acme minLength: 1 scopes: type: string description: Space-separated scopes; defaulted by provider type if omitted type: type: string enum: - GITHUB - GITLAB - SLACK - OUTLINE required: - clientId - clientSecret - registrationId - type CreatePracticeGroupRequest: type: object description: Request to create a new practice group properties: color: type: string description: Optional palette colour key for the group's chip example: rose maxLength: 32 minLength: 0 pattern: "^[a-z]+$" description: type: string description: What this group develops maxLength: 5000 minLength: 0 displayOrder: type: integer format: int32 description: Sort order within the workspace. Appended when omitted. example: 1 minimum: 0 icon: type: string description: Optional lucide icon name giving the group a glanceable identity example: ShieldAlert maxLength: 64 minLength: 0 pattern: "^[A-Za-z0-9]+$" name: type: string description: Human-readable name example: Submitting review-ready work maxLength: 128 minLength: 3 slug: type: string description: URL-safe identifier unique within the workspace example: review-ready-work maxLength: 64 minLength: 3 pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$" required: - name - slug CreatePracticeRequest: type: object additionalProperties: false description: Request to create a new practice definition properties: automatedReviewPolicy: $ref: "#/components/schemas/PracticeAutomatedReviewPolicy" description: Versioned review settings; omit to use the recommended ones for the work type the signals name criteria: type: string description: Practice review criteria maxLength: 50000 minLength: 0 deliveryBehavior: $ref: "#/components/schemas/PracticeDeliveryBehavior" evidenceRequirements: type: array items: $ref: "#/components/schemas/PracticeEvidenceRequirement" groupSlug: type: - string - "null" description: Practice group to add the practice to. Omit or set to null for Unassigned. name: type: string description: Human-readable name example: PR Description Quality maxLength: 128 minLength: 3 precomputeScript: type: string description: TypeScript/Node static analysis run before automated review maxLength: 100000 minLength: 0 precondition: $ref: "#/components/schemas/PracticePrecondition" reviewWhen: type: object additionalProperties: type: array items: type: string uniqueItems: true description: Automatic review state selections. An empty object imposes no state restrictions. Each selected dimension requires a nonempty set of non-null values offered by the work type descriptor. Values within a dimension are alternatives; all selected dimensions must match. signals: type: array items: type: string maxItems: 2147483647 minItems: 1 slug: type: string description: URL-safe identifier unique within the workspace example: pr-description-quality maxLength: 64 minLength: 3 pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$" subject: type: string enum: - AUTHOR - ASSIGNEE - REVIEWER - MERGER whatGoodLooksLike: type: string description: "Developer-facing exemplar; a concrete instance, not the review\ \ criteria" maxLength: 2000 minLength: 0 whyItMatters: type: string description: Plain-language rationale shown to the developer maxLength: 2000 minLength: 0 required: - criteria - evidenceRequirements - name - signals - slug CreateReviewBackfillRunRequest: type: object description: |- Ask for a campaign to be enumerated and costed. Creates nothing that spends money: the run comes back awaiting confirmation, and only a subsequent status change starts it. properties: artifactKind: type: string description: Kind of work to review enum: - scm.pull_request - scm.issue example: scm.pull_request fromAt: type: string format: date-time description: "Window start, inclusive, over the artifact's creation time" toAt: type: string format: date-time description: "Window end, exclusive" required: - artifactKind - fromAt - toAt CreateReviewRequest: type: object description: The piece of work a review is being asked for properties: artifactId: type: integer format: int64 description: "The artifact's internal id, as the trace and review listings\ \ report it" exclusiveMinimum: 0 artifactKind: type: string description: "The artifact kind's wire id, e.g. scm.pull_request. A raw\ \ string rather than a closed enum because kinds are an open vocabulary:\ \ a build that has never heard of a kind should refuse it by name, not\ \ fail to parse the request." example: scm.pull_request minLength: 1 required: - artifactId - artifactKind CreateReviewSweepScheduleRequest: type: object description: |- Create a standing instruction to sweep this workspace's recent work.

Unlike a backfill campaign there is no separate confirmation step: this request is the authorisation to spend on the cadence it names, and it is recorded against the account that made it.

There is deliberately no repository or author list. Which repositories are reviewed is the workspace's review scope and whose work is reviewed is the practice-review role; both already apply to every review this workspace runs, a sweep included. properties: artifactKind: type: string description: Kind of work to sweep enum: - scm.pull_request - scm.issue example: scm.pull_request cadence: type: string description: How often the sweep runs enum: - DAILY - WEEKLY lookbackDays: type: integer format: int32 description: "How far back each sweep looks, in days" example: 2 maximum: 7 minimum: 1 required: - artifactKind - cadence - lookbackDays CreateSurvey: type: object properties: description: type: string maxLength: 500 minLength: 0 endsAt: type: string format: date-time purpose: type: string enum: - PRODUCT - RESEARCH questions: type: array items: $ref: "#/components/schemas/Question" maxItems: 20 minItems: 0 startsAt: type: string format: date-time title: type: string maxLength: 160 minLength: 0 workspaceId: type: integer format: int64 required: - description - purpose - questions - startsAt - title CreateWorkspaceLlmConnectionRequest: type: object description: Connect your own AI provider properties: apiKey: type: string description: API key (write-only; never returned) apiProtocol: type: string description: Wire protocol example: openai-responses minLength: 1 pattern: openai-completions|openai-responses authMode: type: string description: Credential shape (default BEARER) enum: - BEARER - API_KEY baseUrl: type: string description: Provider base URL maxLength: 2048 minLength: 0 connectionPlatform: type: string description: Admin-declared connection platform; null when not declared enum: - LOGOS - VLLM - OLLAMA - AZURE - AWS_BEDROCK - GOOGLE_VERTEX - OPENAI - GOOGLE_AI_STUDIO - ALIBABA_CLOUD - GROQ - FIREWORKS - TOGETHER_AI - DEEPINFRA - NEBIUS - OPENROUTER - CLOUDFLARE_AI_GATEWAY - VERCEL_AI_GATEWAY displayName: type: string description: Human-readable name maxLength: 128 minLength: 0 enabled: type: boolean description: Whether the connection is active (default false) slug: type: string description: Optional internal slug; generated from displayName when omitted maxLength: 63 minLength: 0 required: - apiProtocol - baseUrl - displayName CreateWorkspaceLlmModelRequest: type: object description: Create a model on your AI provider properties: brand: type: string description: Model brand declared by an admin; display only enum: - OPENAI - ANTHROPIC - GEMINI - GEMMA - META - MISTRAL - QWEN - DEEPSEEK - XAI - COHERE - Z_AI - MOONSHOT contextWindow: type: integer format: int32 description: Context window in tokens minimum: 1 dataHandlingNote: type: string description: "Admin-only note: region, agreement, renewal date" maxLength: 200 minLength: 0 displayName: type: string description: Human-readable name maxLength: 128 minLength: 0 enabled: type: boolean description: Whether the model is active (default false) maxOutputTokens: type: integer format: int32 description: Maximum output tokens minimum: 1 operatedBy: type: string description: Who operates the systems the work is sent to; omit to leave the model undeclared enum: - OWN_ORGANISATION - PROVIDER per1mCacheReadUsd: type: number format: decimal description: "Cache-read rate per 1M tokens (USD), if applicable" per1mCacheWriteUsd: type: number format: decimal description: "Cache-write rate per 1M tokens (USD), if applicable" per1mInputUsd: type: number format: decimal description: Input rate per 1M tokens (USD); required when the model has a price per1mOutputUsd: type: number format: decimal description: Output rate per 1M tokens (USD); required when the model has a price priceNote: type: string description: "Note; required when the model is free (e.g. self-hosted, no\ \ cost)" maxLength: 500 minLength: 0 pricingMode: type: string description: Pricing mode (default UNPRICED) enum: - PRICED - NO_CHARGE - UNPRICED reasoningEffort: type: string description: "Reasoning effort to request; null sends none, so the provider's\ \ own default applies" enum: - NONE - MINIMAL - LOW - MEDIUM - HIGH - XHIGH - MAX slug: type: string description: Optional internal slug; generated from displayName when omitted maxLength: 63 minLength: 0 upstreamModelId: type: string description: Upstream provider model id maxLength: 256 minLength: 0 required: - displayName - upstreamModelId CreateWorkspaceRequest: type: object description: Request to create a new workspace properties: accountLogin: type: string description: Git provider account login (GitHub org/user or GitLab group path) example: my-org maxLength: 255 minLength: 0 accountType: type: string description: Type of account (USER or ORG) enum: - ORG - USER displayName: type: string description: Human-readable name of the workspace example: My Workspace maxLength: 120 minLength: 0 kind: type: string description: "Integration kind to provision. SLACK flows through OAuth,\ \ not this endpoint." enum: - GITHUB - GITLAB example: GITLAB ownerUserId: type: integer format: int64 deprecated: true description: "Deprecated: ignored by the server. The authenticated user\ \ always becomes the owner." personalAccessToken: type: string description: Personal Access Token. Required for both kinds (GitLab API or GitHub PAT). Stored encrypted at rest. example: glpat-... maxLength: 512 minLength: 0 serverUrl: type: string description: "For GitLab, the default GitLab instance this server reads\ \ from, which is also used when omitted; any other instance is refused." example: https://gitlab.example.com workspaceSlug: type: string description: Non-reserved lowercase ASCII DNS label. Consecutive hyphens are prohibited. example: my-workspace maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" required: - accountLogin - accountType - displayName - kind - workspaceSlug CsrfToken: type: object properties: headerName: type: string token: type: string required: - headerName - token CuratedCatalog: type: object properties: customOrder: type: boolean etag: type: string description: Strong entity tag to send in If-Match when reordering this catalog groups: type: array items: $ref: "#/components/schemas/CuratedGroup" practices: type: array items: $ref: "#/components/schemas/CuratedPracticeSummary" summary: $ref: "#/components/schemas/CuratedCatalogSummary" required: - customOrder - etag - groups - practices - summary CuratedCatalogSummary: type: object properties: editedHere: type: integer format: int32 noLongerShipped: type: integer format: int32 notOffered: type: integer format: int32 total: type: integer format: int32 updatesChangingPresentation: type: integer format: int32 updatesChangingReview: type: integer format: int32 updatesChangingWordingOnly: type: integer format: int32 yours: type: integer format: int32 required: - editedHere - noLongerShipped - notOffered - total - updatesChangingPresentation - updatesChangingReview - updatesChangingWordingOnly - yours CuratedGroup: type: object properties: definition: $ref: "#/components/schemas/CuratedGroupRequest" position: type: integer format: int32 shipped: $ref: "#/components/schemas/CuratedGroupRequest" slug: type: string status: $ref: "#/components/schemas/CatalogEntryStatus" required: - definition - position - slug - status CuratedGroupRequest: type: object description: A complete curated practice group definition properties: color: type: string maxLength: 32 minLength: 0 description: type: string maxLength: 2000 minLength: 0 icon: type: string maxLength: 64 minLength: 0 name: type: string maxLength: 128 minLength: 3 required: - name CuratedPractice: type: object properties: definition: $ref: "#/components/schemas/CuratedPracticeDefinition" position: type: integer format: int32 shipped: $ref: "#/components/schemas/CuratedPracticeDefinition" slug: type: string status: $ref: "#/components/schemas/CatalogEntryStatus" required: - definition - position - slug - status CuratedPracticeDefinition: type: object description: A resolved curated practice definition properties: artifactKind: type: string automatedReviewPolicy: $ref: "#/components/schemas/PracticeAutomatedReviewPolicy" automatedReviewValidation: $ref: "#/components/schemas/PracticeAutomatedReviewValidation" criteria: type: string deliveryBehavior: $ref: "#/components/schemas/PracticeDeliveryBehavior" evidenceRequirements: type: array items: $ref: "#/components/schemas/PracticeEvidenceRequirement" groupSlug: type: string name: type: string precomputeScript: type: string precondition: $ref: "#/components/schemas/PracticePrecondition" reviewWhen: type: object additionalProperties: type: array items: type: string uniqueItems: true description: Automatic review state selections. An empty object imposes no state restrictions. Each selected dimension requires a nonempty set of non-null values offered by the work type descriptor. Values within a dimension are alternatives; all selected dimensions must match. signals: type: array items: type: string subject: type: string enum: - AUTHOR - ASSIGNEE - REVIEWER - MERGER whatGoodLooksLike: type: string whyItMatters: type: string required: - artifactKind - automatedReviewPolicy - automatedReviewValidation - criteria - deliveryBehavior - evidenceRequirements - name - reviewWhen - signals - subject CuratedPracticeRequest: type: object additionalProperties: false description: A complete curated practice definition properties: automatedReviewPolicy: $ref: "#/components/schemas/PracticeAutomatedReviewPolicy" description: Versioned review settings; omit to use the recommended settings for the selected work type criteria: type: string maxLength: 50000 minLength: 0 definitionChanges: type: array description: Explicit intent to change the gate or the person judged items: type: string enum: - PRECONDITION - SUBJECT uniqueItems: true deliveryBehavior: $ref: "#/components/schemas/PracticeDeliveryBehavior" evidenceRequirements: type: array items: $ref: "#/components/schemas/PracticeEvidenceRequirement" groupSlug: type: string maxLength: 64 minLength: 0 name: type: string maxLength: 128 minLength: 3 precomputeScript: type: string maxLength: 100000 minLength: 0 precondition: $ref: "#/components/schemas/PracticePrecondition" reviewWhen: type: object additionalProperties: type: array items: type: string uniqueItems: true description: Automatic review state selections. An empty object imposes no state restrictions. Each selected dimension requires a nonempty set of non-null values offered by the work type descriptor. Values within a dimension are alternatives; all selected dimensions must match. signals: type: array items: type: string maxItems: 2147483647 minItems: 1 subject: type: string enum: - AUTHOR - ASSIGNEE - REVIEWER - MERGER whatGoodLooksLike: type: string maxLength: 2000 minLength: 0 whyItMatters: type: string maxLength: 2000 minLength: 0 required: - criteria - evidenceRequirements - name - signals CuratedPracticeSummary: type: object properties: artifactKind: type: string automatedReview: $ref: "#/components/schemas/PracticeAutomatedReview" effectivelyOffered: type: boolean groupSlug: type: string name: type: string position: type: integer format: int32 slug: type: string status: $ref: "#/components/schemas/CatalogEntryStatus" required: - artifactKind - automatedReview - effectivelyOffered - name - position - slug - status CurrentUserView: type: object properties: accessTokenExpiresAt: type: integer format: int64 appRole: type: string avatarUrl: type: string displayName: type: string gitProviderId: type: string id: type: integer format: int64 identityProvider: type: string linkedProviders: type: array items: $ref: "#/components/schemas/LinkedProvider" primaryEmail: type: string profileUrl: type: string roles: type: array items: type: string status: type: string username: type: string DecideFeedbackProposalRequest: type: object properties: decision: type: string enum: - APPROVED - REJECTED rejectionNote: type: string maxLength: 500 minLength: 0 rejectionReason: type: string enum: - INCORRECT - MISSING_CONTEXT - UNHELPFUL - DUPLICATE - INAPPROPRIATE_PLACEMENT - OTHER required: - decision DeliveredFeedbackPractice: type: object description: The practice's authoritative display name and stable workspace slug. properties: name: type: string slug: type: string required: - name - slug DeliveredWorkFeedback: type: object description: The caller's in-context feedback with recorded provider comments on one authorized piece of work; no feedback bodies properties: feedback: type: array items: $ref: "#/components/schemas/DeliveredWorkFeedbackItem" hasMore: type: boolean description: Older delivered feedback exists beyond this bounded view work: $ref: "#/components/schemas/ReviewedWorkRef" required: - feedback - hasMore - work DeliveredWorkFeedbackItem: type: object properties: deliveredAt: type: string format: date-time id: type: string format: uuid placements: type: array items: $ref: "#/components/schemas/DeliveredWorkFeedbackPlacement" practices: type: array items: $ref: "#/components/schemas/DeliveredFeedbackPractice" required: - id - placements - practices DeliveredWorkFeedbackPlacement: type: object properties: commentRef: type: string description: "Opaque recorded provider comment identity, for deduplication\ \ within this work only; never a URL" endLine: type: integer format: int32 id: type: string format: uuid path: type: string permalink: type: string description: "Provider-returned link on this exact work, or a matching mirrored\ \ comment; absent when unavailable. A recorded placement is not a live\ \ existence check." side: type: string enum: - OLD - NEW startLine: type: integer format: int32 type: type: string enum: - SUMMARY - INLINE - CONVERSATION_TURN - LOCATION_COMMENT required: - commentRef - id - type DeliveryPolicyFactsSnapshot: type: object properties: artifactKind: type: string baseBranch: type: string branchMatched: type: boolean contributingPractices: type: array items: $ref: "#/components/schemas/PracticeFact" deliveryStatus: type: string enum: - ACTIVE - PAUSED personMatched: type: boolean personMode: type: string enum: - ALL_ELIGIBLE - SELECTED recipientConsent: type: boolean repository: type: string repositoryMatched: type: boolean repositoryMode: type: string enum: - ALL_MONITORED - SELECTED subject: type: string enum: - RESOLVED_LINKED_HUMAN - MISSING - NON_HUMAN - UNLINKED triggerMode: type: string enum: - AUTO - MANUAL DeliveryPolicyTrace: type: object properties: admittedRevision: type: integer format: int64 allowed: type: boolean checks: type: array items: $ref: "#/components/schemas/DeliveryPolicyTraceCheck" decisiveReason: type: string enum: - VOLUME_CAPPED - COMPOSER_DEDUPED - COMPOSER_WITHHELD - REPEATS_DELIVERED_NOTE - REACTED_DISPUTED - REACTED_NOT_APPLICABLE - CONVERSATION_EXPIRED - ARTIFACT_GONE - ARTIFACT_CLOSED - ISSUE_SNAPSHOT_CHANGED - ARTIFACT_MERGED - PUBLIC_SUBJECT_INELIGIBLE - ARTIFACT_DRAFT - RECIPIENT_OPTED_OUT - EMPTY_AFTER_SANITIZE - INSTANCE_SILENCED - WORKSPACE_DISABLED - WORKSPACE_DELIVERY_PAUSED - STALE_ROLLOUT_REVISION - OUTSIDE_CURRENT_COVERAGE - APPROVAL_STALE - APPROVAL_NO_LONGER_ELIGIBLE - PRACTICE_REQUIRES_APPROVAL - BACKFILL_QUIET - OBSERVATION_INVALIDATED - REVIEWED_REVISION_CHANGED evaluatedAt: type: string format: date-time evaluatedRevision: type: integer format: int64 facts: $ref: "#/components/schemas/DeliveryPolicyFactsSnapshot" resolverVersion: type: string reviewId: type: string format: uuid stage: type: string enum: - COMPOSITION - AUTOMATIC - APPROVED - EGRESS surface: type: string enum: - ARTIFACT - IN_APP - CONVERSATION required: - admittedRevision - allowed - checks - evaluatedAt - facts - resolverVersion - reviewId - stage - surface DeliveryPolicyTraceCheck: type: object properties: check: type: string enum: - INSTANCE_SILENT_MODE - WORKSPACE_ENABLED - ROLLOUT_REVISION - WORKSPACE_DELIVERY - CURRENT_COVERAGE - PRACTICE_AUTHORITY - RECIPIENT_CONSENT - ARTIFACT_ELIGIBILITY status: type: string enum: - PASSED - DENIED - NOT_APPLICABLE - NOT_REACHED required: - check - status DeveloperPracticeSummary: type: object description: Per-practice observation summary for a developer properties: lastObservedAt: type: string format: date-time description: Timestamp of most recent observation met: type: integer format: int64 description: Number of MET observations notApplicable: type: integer format: int64 notMet: type: integer format: int64 description: Number of NOT_MET observations practiceName: type: string description: Practice name practiceSlug: type: string description: Practice slug totalObservations: type: integer format: int64 description: Total number of observations undetermined: type: integer format: int64 required: - met - notApplicable - notMet - practiceName - practiceSlug - totalObservations - undetermined EmailTestRequest: type: object properties: to: type: string format: email description: the mailbox to send the test email to; blank means the caller's own verified address maxLength: 254 minLength: 0 EmailTestResponse: type: object properties: messageId: type: string description: "the accepted Message-ID, only for SENT;\ \ search for it in the relay's log" outcome: type: string description: what became of the test email; SENT is the only success enum: - SENT - EXPIRED - NOT_CONFIGURED - SILENT_MODE - NO_RECIPIENT - UNSUBSCRIBED - INVALID_ADDRESS - REJECTED - UNAVAILABLE - RATE_LIMITED to: type: string description: "the address it went to, or null when there was\ \ no recipient to resolve" required: - outcome ErasureRequest: type: object properties: externalCopiesRemoved: type: boolean required: - externalCopiesRemoved EvidenceCitation: type: object description: A verified quote and its exact source location properties: artifactPath: type: string endLine: type: integer format: int32 path: type: string quote: type: string quoteRedacted: type: boolean revision: type: string side: type: string enum: - OLD - NEW sourceKind: type: string startLine: type: integer format: int32 required: - artifactPath - endLine - path - quoteRedacted - sourceKind - startLine EvidenceInapplicability: type: object description: Why this practice had nothing to judge in this work properties: consulted: type: array description: "The sources the review read to conclude this, by source kind" items: type: string ruledOutBy: type: string description: The fact about this work that means there was nothing to look at subject: type: string description: What this practice looks for required: - consulted - ruledOutBy - subject EvidenceSearch: type: object description: Where the review looked when it found nothing properties: boundary: type: string description: How far the search reached — the work this absence holds over consulted: type: array description: "The sources the review searched, by source kind" items: type: string lookedFor: type: string description: What the review looked for in this work required: - boundary - consulted - lookedFor EvidenceUndecidability: type: object description: "What the review could not settle, and what would settle it" properties: openQuestion: type: string description: The question this work left open wouldSettleIt: type: string description: What would have answered it required: - openQuestion - wouldSettleIt ExportCreated: type: object description: Acknowledgement returned when a data export is requested. properties: id: type: integer format: int64 status: type: string ExportStatus: type: object description: Status of a requested data export; timestamps are null until the matching transition occurs. properties: completedAt: type: string format: date-time expiresAt: type: string format: date-time id: type: integer format: int64 requestedAt: type: string format: date-time status: type: string ExternalDelivery: type: object properties: locator: type: string workspaceId: type: integer format: int64 required: - locator - workspaceId FeatureFlags: type: object description: Feature flags evaluated for the current user properties: ADMIN: type: boolean description: User has admin privileges GITLAB_WORKSPACE_CREATION: type: boolean description: GitLab workspace creation feature is enabled NOTIFICATION_ACCESS: type: boolean description: User can receive notifications FeedbackAccountRef: type: object description: "Who produced a record, as an administrator sees it; absent once\ \ the account is erased." properties: displayName: type: string email: type: string id: type: integer format: int64 required: - displayName - id FeedbackApproval: type: object properties: actorAccountId: type: integer format: int64 decidedAt: type: string format: date-time decision: type: string enum: - APPROVED - REJECTED feedbackId: type: string format: uuid rejectionNote: type: string rejectionReason: type: string enum: - INCORRECT - MISSING_CONTEXT - UNHELPFUL - DUPLICATE - INAPPROPRIATE_PLACEMENT - OTHER FeedbackDispute: type: object description: "A developer's standing dispute of feedback written for them. The\ \ explanation is theirs, written to the workspace's administrators; the feedback's\ \ own text stays as private as its channel keeps it." properties: channel: type: string enum: - IN_CONTEXT - IN_CHAT - IN_APP disputedAt: type: string format: date-time explanation: type: string description: "Why the developer thinks the feedback is wrong, in their words" feedbackId: type: string format: uuid required: - channel - disputedAt - explanation - feedbackId FeedbackItem: type: object properties: account: $ref: "#/components/schemas/FeedbackAccountRef" appVersion: type: string createdAt: type: string format: date-time id: type: string format: uuid kind: type: string enum: - IDEA - BUG - FEEDBACK message: type: string pagePath: type: string resolvedAt: type: string format: date-time resolvedBy: $ref: "#/components/schemas/FeedbackAccountRef" userAgent: type: string workspace: $ref: "#/components/schemas/FeedbackWorkspaceRef" required: - createdAt - id - kind - message FeedbackRequest: type: object properties: kind: type: string enum: - IDEA - BUG - FEEDBACK message: type: string maxLength: 5000 minLength: 0 pagePath: type: string maxLength: 500 minLength: 0 pattern: "/(?!/)[^?#\\p{Cc}]*" userAgent: type: string maxLength: 500 minLength: 0 pattern: "[^\\p{Cc}]*" required: - kind - message FeedbackResolutionCounts: type: object description: Feedback resolution counts for the current developer properties: addressed: type: integer format: int64 disputed: type: integer format: int64 notApplicable: type: integer format: int64 FeedbackResponse: type: object description: The recipient's current assessment and resolution of delivered feedback properties: comment: type: string feedbackId: type: string format: uuid resolution: type: string enum: - ADDRESSED - DISPUTED - NOT_APPLICABLE respondedAt: type: string format: date-time usefulness: type: string enum: - HELPFUL - UNHELPFUL required: - feedbackId FeedbackResponseRequest: type: object description: The complete response to delivered feedback properties: comment: type: string description: Optional explanation; required when resolution is DISPUTED. maxLength: 2000 minLength: 0 resolution: type: string description: What the recipient decided to do with the feedback enum: - ADDRESSED - DISPUTED - NOT_APPLICABLE usefulness: type: string description: How useful the feedback was enum: - HELPFUL - UNHELPFUL FeedbackSourceCount: type: object description: Distinct work artifacts of one kind that contributed feedback properties: count: type: integer format: int64 description: Distinct artifacts of this kind in the selected time period workKind: type: string description: The kind of work the feedback came from required: - count - workKind FeedbackTriage: type: object properties: resolved: type: boolean required: - resolved FeedbackWithdrawal: type: object description: "One withdrawal of a card from a developer's practice page, and\ \ its restoration if any" properties: id: type: string format: uuid reason: type: string restorationReason: type: string description: Why it was restored; null while the withdrawal is in force restoredAt: type: string format: date-time restoredBy: type: string description: Who restored it; null while in force or once that account is erased withdrawnAt: type: string format: date-time withdrawnBy: type: string description: Who withdrew it; null once that account is erased required: - id - reason - withdrawnAt FeedbackWorkspaceRef: type: object description: The workspace a record was submitted from; absent for instance-level submissions. properties: displayName: type: string id: type: integer format: int64 slug: type: string required: - displayName - id - slug FirstLoginConsent: type: object properties: noticeVersion: type: string participateInResearch: type: boolean description: "Required when the instance names a research organization,\ \ omitted otherwise" researchOrganization: type: string description: The organization the research question named on screen; omitted when it asked none termsAccepted: type: boolean required: - noticeVersion - termsAccepted FxRateInfo: type: object description: "Display-only currency conversion for the USD amounts in this response.\ \ Multiply a USD amount by ratePerUsd to get the display-currency estimate;\ \ always label it as an estimate and show rateDate, which is the date the\ \ rate was actually published on (not necessarily today), and attribute it\ \ to source." properties: currencyCode: type: string description: ISO 4217 code of the display currency example: EUR rateDate: type: string format: date description: "The date the underlying reference rate was published. A closed\ \ month always reports a date inside that month, so its converted figure\ \ never changes once the month ends." example: 2026-07-24 ratePerUsd: type: number format: decimal description: "Units of the display currency per 1 USD, at 6 decimal places" example: 0.878966 source: type: string description: "Who published the rate, so a disclosure can name it instead\ \ of saying \"a reference rate\". ECB = the European Central Bank's daily\ \ euro foreign-exchange reference rates." enum: - ECB example: ECB required: - currencyCode - rateDate - ratePerUsd - source GeneratedPathReview: type: object description: "Generated-path policy used by this review, not the repository's\ \ current settings" properties: paths: type: array description: "Changed paths marked generated, including both names of a\ \ rename" items: type: string patterns: type: array items: type: string required: - paths - patterns GitHubProvider: type: object description: GitHub provider configuration properties: appInstallationUrl: type: string description: GitHub App installation URL example: https://github.com/apps/hephaestus/installations/new GitLabGroup: type: object description: GitLab group accessible to the provided PAT properties: avatarUrl: type: string description: Group avatar URL fullPath: type: string description: Full group path including parent groups example: my-org/my-team id: type: integer format: int64 description: GitLab group numeric ID name: type: string description: Group display name visibility: type: string description: "Group visibility: public, internal, or private" webUrl: type: string description: Group web URL required: - fullPath - id - name GitLabPreflightRequest: type: object description: Request to validate a GitLab PAT or list accessible groups before workspace creation properties: groupFullPath: type: string description: "GitLab group full path, used to validate the token against\ \ the group when /api/v4/user refuses it" example: my-org/my-team personalAccessToken: type: string description: GitLab Personal Access Token to validate example: your-gitlab-token minLength: 1 serverUrl: type: string description: "The default GitLab instance this server reads from, which\ \ is also used when omitted; any other instance is refused." example: https://gitlab.example.com required: - personalAccessToken GitLabPreflightResponse: type: object description: Result of GitLab PAT validation properties: error: type: string description: Error message if validation failed userId: type: integer format: int64 description: GitLab user ID or group ID username: type: string description: Username of the token owner (personal tokens) or group name (group tokens) valid: type: boolean description: Whether the token is valid required: - valid GitLabProvider: type: object description: GitLab provider configuration properties: defaultServerUrl: type: string description: Origin of the one GitLab instance workspaces are created on example: https://gitlab.lrz.de GroupAutonomyRollup: type: object description: One group's practice counts per effective autonomy state properties: autonomy: $ref: "#/components/schemas/AutonomyAssignment" description: "The autonomy in force for this group, and where it came from" counts: type: object additionalProperties: type: integer format: int32 description: Practice count per effective autonomy in this group groupName: type: string description: Group name; null for the no-group group groupSlug: type: string description: Group slug; null groups the practices that belong to no group overriddenCount: type: integer format: int32 description: Number of practices with an explicit autonomy override required: - autonomy - counts - overriddenCount HeldPractice: type: object description: A practice the developer's newest work keeps meeting properties: cleanWork: type: integer format: int32 description: How many of the newest pieces of work in a row came back clean groupSlug: type: string holdsAs: type: string description: "What the developer keeps doing, in the catalog's words; absent\ \ for a practice the catalog does not ship" practiceName: type: string practiceSlug: type: string since: type: string format: date-time description: When the oldest piece of work of the clean run was reviewed workKind: type: string description: Artifact kind id most of that work is workProvider: type: string description: "The provider most of that work lives at, which decides its\ \ noun: a GitLab scm.pull_request is a merge request; absent when no run\ \ that reviewed the work is left" enum: - GITHUB - GITLAB - SLACK - OUTLINE required: - cleanWork - practiceName - practiceSlug - since - workKind Identity: type: object properties: providerId: type: integer format: int64 exclusiveMinimum: 0 subject: type: string maxLength: 255 minLength: 1 teamId: type: string maxLength: 255 minLength: 1 required: - providerId - subject IdentityProviderView: type: object description: |- One row per sign-in option. providerType drives the SPA's icon choice; baseUrl is the OAuth instance origin (scheme + host[:port]) of the authorization endpoint, so the workspace-creation wizard can match a target instance to its login.

baseUrl is the OAuth origin, not the SCM API origin. It is only meaningful for GitLab rows, where the OAuth origin and the API origin coincide (e.g. https://gitlab.example.com). For a GitHub row it is https://github.com (the OAuth host), NOT https://api.github.com; the sole consumer (the workspace wizard) matches GitLab self-hosted origins and never relies on the GitHub value, so the discrepancy is harmless. Do not treat this as an SCM API base URL. properties: baseUrl: type: string displayName: type: string providerType: type: string registrationId: type: string IdentityView: type: object properties: avatarUrl: type: string displayName: type: string id: type: integer format: int64 lastLoginAt: type: string format: date-time providerType: type: string subject: type: string username: type: string required: - id - providerType - subject InAppCleanWork: type: object description: One piece of work that came back clean on the practice since the feedback was prepared properties: reviewedAt: type: string format: date-time description: When that piece was reviewed reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" description: "The piece of work, as every surface names it" required: - reviewedAt - reviewedWork InAppEvidence: type: object description: One piece of work the pattern was observed on properties: observedAt: type: string format: date-time description: When the measurement behind this occurrence was taken outcome: type: string description: "What the review made of this piece of work: a behaviour demonstrated,\ \ a trap avoided, something harmful done, or something needed left out" enum: - MET - NOT_MET - NOT_APPLICABLE - UNDETERMINED reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" description: "The piece of work, as every surface names it" summary: type: string description: What the review recorded on this piece of work required: - observedAt - outcome - reviewedWork InAppFeedback: type: object description: A process-level message on the developer's own practice pages properties: body: type: string description: "The message, as Markdown, without the headline and the next\ \ step; null once a workspace admin withdrew it" cleanNeeded: type: integer format: int32 description: Clean pieces of work in a row on the practice that resolve this feedback cleanWork: type: array description: "The pieces of work in a row that came back clean on the practice\ \ since the feedback was prepared, each with the date it was reviewed,\ \ oldest first, at most cleanNeeded of them; a problem empties it, and\ \ once resolved these are exactly the pieces that resolved it" items: $ref: "#/components/schemas/InAppCleanWork" closedAt: type: string format: date-time description: "When it stopped being open: the earliest of the work completing\ \ its clean run, the developer answering that it is addressed or not applicable,\ \ and the practice changing its review rules after it was prepared; null\ \ while it is open" closedBy: type: string description: "What closed it, for the moment closedAt names; on a tie the\ \ work, then the developer, then the practice; null while it is open" enum: - WORK - DEVELOPER - PRACTICE_CHANGED evidence: type: array description: "The pieces of work the way of working was observed on, newest\ \ first" items: $ref: "#/components/schemas/InAppEvidence" groupName: type: string description: Group display name; null when the practice has none groupSlug: type: string description: Group the practice sits in; null when the practice has none headline: type: string description: "Short headline naming the way of working, never the person" id: type: string format: uuid nextStep: type: string description: "The way of working to try next, on its own; null for feedback\ \ prepared without one" practiceName: type: string practiceSlug: type: string description: Practice this feedback is about preparedAt: type: string format: date-time description: When the message was composed readAt: type: string format: date-time description: When this developer first opened it; null until they have response: $ref: "#/components/schemas/FeedbackResponse" description: The developer's current response to this feedback; null while they have none whatGoodLooksLike: type: string description: "What good looks like, in the developer's framing" whyItMatters: type: string description: "Why this practice matters, in the developer's framing" withdrawnAt: type: string format: date-time description: "When a workspace admin withdrew it because what it said was\ \ wrong; the card then carries only its practice, whose name is the headline,\ \ and no message, next step, evidence, progress or closure" required: - cleanNeeded - cleanWork - evidence - headline - id - practiceName - practiceSlug - preparedAt InitiateConnectionRequest: type: object description: |- Inbound payload for POST /workspaces/{workspaceSlug/connections}.

userInput is intentionally a free-form map so per-kind ConnectionStrategy implementations can dictate their own field schema (e.g. Outline needs server_url; GitHub needs nothing because the install URL is server-configured). properties: kind: type: string enum: - GITHUB - GITLAB - SLACK - OUTLINE userInput: type: object additionalProperties: type: string required: - kind InitiateConnectionResponse: type: object description: |- Flat response for POST /workspaces/{workspaceSlug/connections}.

Two outcomes, distinguished by type:

Deliberately a flat record (nullable per-variant fields) rather than a sealed oneOf hierarchy: a discriminated union serialises to OpenAPI oneOf + discriminator, which the webapp's hey-api react-query transformer mishandles. A flat shape round-trips cleanly through code generation, so the webapp consumes the generated client instead of a hand-rolled fetch wrapper. properties: connectionId: type: integer format: int64 type: type: string enum: - REDIRECT - LINKED vendorUrl: type: string format: uri required: - type InstanceLlmSettings: type: object description: Instance-wide LLM governance settings properties: allowWorkspaceConnections: type: boolean description: Whether workspaces may register their own LLM connections allowedEgressHosts: type: string description: Comma/newline-delimited egress host allowlist; blank = allow any public host example: "api.openai.com, llm-gateway.example.com" required: - allowWorkspaceConnections InstanceSettings: type: object properties: etag: type: string silentModeChangedAt: type: string format: date-time silentModeChangedByAccountId: type: integer format: int64 silentModeEngaged: type: boolean silentModeReason: type: string required: - etag - silentModeEngaged IntegrationCatalogEntry: type: object description: Integration kind availability + connection status for this workspace properties: connected: type: boolean description: Whether this workspace has a (non-UNINSTALLED) connection for this kind connectionId: type: integer format: int64 description: "Connection id, if connected" connectionState: type: string description: "Connection state, if connected" enum: - PENDING - ACTIVE - SUSPENDED - UNINSTALLED credentialsUnreadableSince: type: string format: date-time description: When the stored credential was first found unreadable with the server's keys; absent while it reads displayName: type: string description: Human-readable display name kind: type: string description: Integration kind enum: - GITHUB - GITLAB - SLACK - OUTLINE required: - connected - displayName - kind LabelInfo: type: object description: Information about a label from a repository properties: color: type: string description: "Hex color code of the label (without #)" example: d73a4a id: type: integer format: int64 description: Unique identifier of the label name: type: string description: Name of the label repository: $ref: "#/components/schemas/RepositoryInfo" description: Repository the label belongs to required: - color - id - name LatestRelease: type: object description: |- A published release. schemaMigrations is the flag the release workflow publishes for that one release and is absent when the notes carry none; it says nothing about releases between the running one and this one. properties: notesUrl: type: string publishedAt: type: string format: date-time schemaMigrations: type: boolean version: type: string required: - notesUrl - publishedAt - version LinkedProvider: type: object description: "A provider instance the current user is linked to: its type +\ \ server-url origin." properties: serverUrl: type: string type: type: string LlmConnection: type: object description: Instance LLM provider connection (API key redacted) properties: apiKeyLast4: type: string description: "Last four characters of the stored API key, if any" apiProtocol: type: string description: Wire protocol example: openai-responses authMode: type: string description: Credential shape enum: - BEARER - API_KEY baseUrl: type: string description: Provider base URL connectionPlatform: type: string description: Admin-declared connection platform enum: - LOGOS - VLLM - OLLAMA - AZURE - AWS_BEDROCK - GOOGLE_VERTEX - OPENAI - GOOGLE_AI_STUDIO - ALIBABA_CLOUD - GROQ - FIREWORKS - TOGETHER_AI - DEEPINFRA - NEBIUS - OPENROUTER - CLOUDFLARE_AI_GATEWAY - VERCEL_AI_GATEWAY createdAt: type: string format: date-time description: Creation timestamp displayName: type: string description: Human-readable name enabled: type: boolean description: Whether the connection is enabled hasApiKey: type: boolean description: Whether an API key is stored id: type: integer format: int64 description: Connection ID slug: type: string description: Unique slug example: openai-prod updatedAt: type: string format: date-time description: Last update timestamp required: - apiProtocol - authMode - baseUrl - createdAt - displayName - enabled - hasApiKey - id - slug LlmModel: type: object description: Instance catalog model properties: brand: type: string description: Model brand declared by an admin; display only enum: - OPENAI - ANTHROPIC - GEMINI - GEMMA - META - MISTRAL - QWEN - DEEPSEEK - XAI - COHERE - Z_AI - MOONSHOT connectionDisplayName: type: string description: Owning connection's display name connectionId: type: integer format: int64 description: Owning connection id contextWindow: type: integer format: int32 description: Context window in tokens createdAt: type: string format: date-time description: Creation timestamp currentPrice: $ref: "#/components/schemas/LlmModelPrice" description: Current price; null if none has ever been set dataHandlingNote: type: string description: "Admin-only note: region, agreement, renewal date" dataHandlingTier: type: string description: Data-handling tier derived from the operator; UNDECLARED until it is set enum: - IN_HOUSE - CLOUD - UNDECLARED displayName: type: string description: Human-readable name enabled: type: boolean description: Active toggle grantedWorkspaceIds: type: array description: Workspace ids shared with; only meaningful when visibility is GRANTED items: type: integer format: int64 id: type: integer format: int64 description: Model id maxOutputTokens: type: integer format: int32 description: Maximum output tokens operatedBy: type: string description: Who operates the systems the work is sent to; null until declared enum: - OWN_ORGANISATION - PROVIDER reasoningEffort: type: string description: "Reasoning effort requested of the model; null sends none,\ \ the provider's default applies" enum: - NONE - MINIMAL - LOW - MEDIUM - HIGH - XHIGH - MAX slug: type: string description: Unique slug within the connection updatedAt: type: string format: date-time description: Last update timestamp upstreamModelId: type: string description: Upstream provider model id visibility: type: string description: Share with all workspaces (PUBLIC) or only selected ones (GRANTED) enum: - PUBLIC - GRANTED required: - connectionDisplayName - connectionId - createdAt - dataHandlingTier - displayName - enabled - grantedWorkspaceIds - id - slug - upstreamModelId - visibility LlmModelPrice: type: object description: "A model's price, per 1M tokens" properties: currency: type: string description: Currency code effectiveFrom: type: string format: date-time description: When this price took effect effectiveTo: type: string format: date-time description: When this price was superseded; null if still current id: type: integer format: int64 description: Price row id note: type: string description: Note per1mCacheReadUsd: type: number format: decimal description: Cache-read rate per 1M tokens (USD) per1mCacheWriteUsd: type: number format: decimal description: Cache-write rate per 1M tokens (USD) per1mInputUsd: type: number format: decimal description: Input rate per 1M tokens (USD) per1mOutputUsd: type: number format: decimal description: Output rate per 1M tokens (USD) pricingMode: type: string description: Pricing mode enum: - PRICED - NO_CHARGE - UNPRICED required: - currency - effectiveFrom - id - pricingMode LlmProbeResult: type: object description: Result of testing an LLM connection's /models endpoint properties: message: type: string description: Human-readable diagnostic when not reachable models: type: array description: Model ids returned by the provider (empty if unreachable) items: type: string reachable: type: boolean description: Whether the provider answered with a successful models listing statusCode: type: integer format: int32 description: "HTTP status returned by the provider, if any" required: - models - reachable LlmUsageByDay: type: object description: Spend for one UTC day properties: day: type: string format: date events: type: integer format: int64 instanceTotalCostUsd: type: number format: decimal description: "Confirmed spend on shared (instance) models for this day,\ \ in USD." ownProviderTotalCostUsd: type: number format: decimal description: "Spend on this workspace's own connected provider(s) for this\ \ day, in USD." unpricedEventCount: type: integer format: int64 description: Calls this day whose price is not yet known. Excluded from both totals above. required: - day - events - instanceTotalCostUsd - ownProviderTotalCostUsd - unpricedEventCount LlmUsageByJobType: type: object description: Month spend aggregated by job type properties: cacheReadTokens: type: integer format: int64 cacheWriteTokens: type: integer format: int64 events: type: integer format: int64 description: Ledger events (jobs / mentor turns) inputTokens: type: integer format: int64 instanceTotalCostUsd: type: number format: decimal description: "Confirmed spend on shared (instance) models for this job type,\ \ in USD." jobType: type: string enum: - PULL_REQUEST_REVIEW - ISSUE_REVIEW - CONVERSATION_REVIEW - DOCUMENT_REVIEW - MENTOR_TURN outputTokens: type: integer format: int64 ownProviderTotalCostUsd: type: number format: decimal description: "Spend on this workspace's own connected provider(s) for this\ \ job type, in USD." totalCalls: type: integer format: int64 description: "LLM API calls, as reported by the runtime. Practice reviews\ \ and mentor turns both include every assistant call in an internal tool\ \ loop." unpricedEventCount: type: integer format: int64 description: Calls for this job type whose price is not yet known. Excluded from both totals above. required: - cacheReadTokens - cacheWriteTokens - events - inputTokens - instanceTotalCostUsd - jobType - outputTokens - ownProviderTotalCostUsd - totalCalls - unpricedEventCount LoginProviderView: type: object description: Admin view of a login provider. The client secret is never included. properties: baseUrl: type: string createdAt: type: string format: date-time displayName: type: string enabled: type: boolean redirectUri: type: string description: Redirect/callback URI to register on the upstream OAuth app registrationId: type: string scopes: type: string seededFromEnv: type: boolean type: type: string updatedAt: type: string format: date-time required: - baseUrl - createdAt - displayName - redirectUri - registrationId - scopes - type - updatedAt MemberAiChoiceRequest: type: object properties: choice: type: string enum: - NO_AI - IN_HOUSE_ONLY - CLOUD required: - choice NotificationPreferences: type: object properties: deliveryConfigured: type: boolean description: This instance has an email transport and sender configured emailAvailable: type: boolean description: The account has an active verified email address etag: type: string productFeedback: type: boolean productSurveys: type: boolean researchSurveys: type: boolean surveySummaries: type: boolean workspaceAlerts: type: boolean required: - deliveryConfigured - emailAvailable - etag - productFeedback - productSurveys - researchSurveys - surveySummaries - workspaceAlerts ObservationDetail: type: object description: Full practice observation detail including delivered feedback and evidence properties: artifactId: type: integer format: int64 description: Artifact entity ID artifactKind: type: string description: Artifact type (e.g. PULL_REQUEST) artifactUrl: type: string description: Link to the reviewed artifact on its platform (null when it cannot be resolved) claimCurrentness: type: string description: "Whether an observation's claim still stands: its practice's\ \ review rules are unchanged and it was not superseded, which an issue's\ \ observations are when a change to its reviewable content is recorded.\ \ It says neither whether a later review ran nor whether the work changed\ \ since it was reviewed. Earlier observation standards and missing fingerprints\ \ are unverifiable under the current whole-practice standard" enum: - CURRENT - STALE - UNVERIFIABLE deliveredFeedback: type: string description: "The summary body of the newest eligible feedback about this\ \ observation to this developer (null when no summary body was recorded,\ \ including delivery through inline notes only)" evidence: $ref: "#/components/schemas/ObservationEvidence" evidenceRationale: type: string description: Evidence-based rationale for the observation feedbackCommentUrls: type: array description: "Links to the comments on the reviewed work that carry the\ \ feedback behind feedbackResponse, summary first (null when that feedback\ \ was not delivered on the work or the platform returned no link)" items: type: string feedbackResponse: $ref: "#/components/schemas/FeedbackResponse" description: "The developer's standing answer and response handle for the\ \ newest eligible feedback about this observation, including inline-only\ \ delivery with no summary body (null when no eligible feedback exists\ \ or the newest eligible feedback has failed delivery)" id: type: string format: uuid description: Observation ID invalidatedAt: type: string format: date-time description: When a workspace admin marked this observation as incorrect; null while it stands. An invalidated observation counts toward nothing current. invalidationReason: type: string description: The admin's reason for the invalidation; null while the observation stands nextStep: type: string description: "The next step the review wrote about this observation, whether\ \ or not the feedback carrying it was delivered (null when it wrote none)" observedAt: type: string format: date-time description: When the observation was made origin: type: string description: What occasioned the measurement; never mix origins in one trend line enum: - LIVE - MANUAL - BACKFILL outcome: type: string description: Result of the practice review enum: - MET - NOT_MET - NOT_APPLICABLE - UNDETERMINED practiceName: type: string description: Practice name practiceSlug: type: string description: Practice slug recurrenceKey: type: string description: Cross-run locus key; null when continuity is unavailable severity: type: string description: Severity level (null unless outcome is NOT_MET) enum: - CRITICAL - MAJOR - MINOR - INFO summary: type: string description: Observation summary required: - artifactId - artifactKind - claimCurrentness - id - observedAt - origin - outcome - practiceName - practiceSlug - summary ObservationEvidence: type: object description: "Verified, source-bound evidence for an observation" properties: citations: type: array items: $ref: "#/components/schemas/EvidenceCitation" inapplicability: $ref: "#/components/schemas/EvidenceInapplicability" description: Why this practice had nothing to judge here; null unless the review recorded a reason search: $ref: "#/components/schemas/EvidenceSearch" description: Where the review looked when it found nothing; null unless it recorded a search undecidability: $ref: "#/components/schemas/EvidenceUndecidability" description: What the review could not settle; null unless it recorded an open question required: - citations ObservationInvalidation: type: object description: "One correction of an observation by a workspace admin, and its\ \ restoration if any" properties: id: type: string format: uuid invalidatedAt: type: string format: date-time invalidatedBy: type: string description: Who invalidated it; null once that account is erased providerCopy: type: string description: What became of the comments Hephaestus had already posted on the provider enum: - PENDING - NONE - UPDATED - INLINE_REMAINS - UNRESOLVED reason: type: string restorationReason: type: string description: Why it was restored; null while the invalidation is in force restoredAt: type: string format: date-time restoredBy: type: string description: Who restored it; null while in force or once that account is erased required: - id - invalidatedAt - providerCopy - reason ObservationList: type: object description: Practice observation summary for list views properties: artifactId: type: integer format: int64 description: Artifact entity ID artifactKind: type: string description: Artifact type (e.g. PULL_REQUEST) claimCurrentness: type: string description: "Whether an observation's claim still stands: its practice's\ \ review rules are unchanged and it was not superseded, which an issue's\ \ observations are when a change to its reviewable content is recorded.\ \ It says neither whether a later review ran nor whether the work changed\ \ since it was reviewed. Earlier observation standards and missing fingerprints\ \ are unverifiable under the current whole-practice standard" enum: - CURRENT - STALE - UNVERIFIABLE id: type: string format: uuid description: Observation ID observedAt: type: string format: date-time description: When the observation was made origin: type: string description: What occasioned the measurement; never mix origins in one trend line enum: - LIVE - MANUAL - BACKFILL outcome: type: string description: Result of the practice review enum: - MET - NOT_MET - NOT_APPLICABLE - UNDETERMINED practiceName: type: string description: Practice name practiceSlug: type: string description: Practice slug severity: type: string description: Severity level (null unless outcome is NOT_MET) enum: - CRITICAL - MAJOR - MINOR - INFO summary: type: string description: Observation summary required: - artifactId - artifactKind - claimCurrentness - id - observedAt - origin - outcome - practiceName - practiceSlug - summary OpenWork: type: object description: What is open for one member right now properties: issues: $ref: "#/components/schemas/WorkItemList" description: Open issues assigned to this member pullRequests: $ref: "#/components/schemas/WorkItemList" description: "Open pull requests this member authored, drafts included" reviewRequests: $ref: "#/components/schemas/WorkItemList" description: Open pull requests by other people that ask this member for a review; drafts are excluded teamReviewRequests: $ref: "#/components/schemas/WorkItemList" description: "Open pull requests by other people that ask one of this member's\ \ teams for a review, and not this member: not asking them directly, and\ \ not yet approved or sent back by them. Drafts are excluded. GitHub only;\ \ GitLab has no team reviewers, so a GitLab workspace lists none." required: - issues - pullRequests - reviewRequests - teamReviewRequests OptionCount: type: object properties: count: type: integer format: int64 value: type: string required: - count - value OutcomeVector: type: object properties: met: type: integer format: int32 notApplicable: type: integer format: int32 notMet: type: integer format: int32 undetermined: type: integer format: int32 required: - met - notApplicable - notMet - undetermined OutlineCollection: type: object description: A mirrored Outline collection with its sync state and live document count properties: collectionId: type: string description: Outline collection id (UUID; the natural key) color: type: string description: Collection color as configured in Outline createdAt: type: string format: date-time description: When the collection was registered for mirroring description: type: string description: Collection description as shown in Outline documentCount: type: integer format: int64 description: Live (non-tombstoned) mirrored document count documentsUpstream: type: integer format: int32 description: Documents upstream reported for this collection at the last enumeration (coverage denominator) exportsSkippedForBudget: type: integer format: int32 description: Exports the last pass skipped because the shared budget ran out (0 on a clean pass) icon: type: string description: Collection icon as configured in Outline id: type: integer format: int64 description: Internal registry row id lastSyncError: type: string description: "Last sync failure for this collection, cleared on the next\ \ clean pass" lastSyncedAt: type: string format: date-time description: "When this collection last completed a full reconcile pass,\ \ if any" name: type: string description: "Collection name as shown in Outline, if known" state: type: string description: Mirror lifecycle state (PAUSED freezes sync but keeps documents) enum: - ENABLED - PAUSED syncStatus: type: string description: Whether a clean full pass has completed since registration or the last resume enum: - PENDING - COMPLETE urlId: type: string description: Outline url id (the short slug in collection URLs) required: - collectionId - createdAt - documentCount - id - state - syncStatus OutlineCollectionCandidate: type: object description: "An Outline collection the token can see, offered in the add-collection\ \ picker" properties: alreadyMirrored: type: boolean description: Whether this collection is already registered for mirroring collectionId: type: string description: Outline collection id (UUID) color: type: string description: Collection color as configured in Outline description: type: string description: Collection description as shown in Outline icon: type: string description: Collection icon as configured in Outline name: type: string description: Collection name as shown in Outline urlId: type: string description: Outline url id (the short slug in collection URLs) required: - alreadyMirrored - collectionId OutlineTokenStatus: type: object description: Live state of the API token behind the workspace's Outline connection properties: accepted: type: boolean description: "Whether Outline still accepts the stored token. False means\ \ revoked, expired or rejected." expiresAt: type: string format: date-time description: When the token lapses. Absent for a key created without an expiry. last4: type: string description: "Last four characters of the token, as Outline reports them" lastActiveAt: type: string format: date-time description: When Outline last saw the token used name: type: string description: "The token's name in Outline. Absent when the token cannot\ \ list its own key (a scoped key, or one owned by a user who cannot see\ \ it) — sync is unaffected." required: - accepted OverviewWindow: type: object description: The span the overview measured change over properties: since: type: string format: date-time description: "The window opens after this moment: the run before the latest\ \ one" until: type: string format: date-time description: "The window closes at this moment, and the profile is read\ \ as of it" required: - since - until PageMetadata: properties: number: type: integer format: int64 size: type: integer format: int64 totalElements: type: integer format: int64 totalPages: type: integer format: int64 PageResponseDTOAgentJob: type: object description: |- Stable wire representation for the APIs that expose flat page metadata. Spring Data's PageImpl is an implementation detail, not a JSON contract; these fields preserve the existing clients' response shape without relying on its bean properties. New APIs use Spring Data's PagedModel. properties: content: type: array items: $ref: "#/components/schemas/AgentJob" empty: type: boolean first: type: boolean last: type: boolean number: type: integer format: int32 numberOfElements: type: integer format: int32 pageable: $ref: "#/components/schemas/Pageable" size: type: integer format: int32 sort: $ref: "#/components/schemas/Sort" totalElements: type: integer format: int64 totalPages: type: integer format: int32 PageResponseDTOAuthEventView: type: object description: |- Stable wire representation for the APIs that expose flat page metadata. Spring Data's PageImpl is an implementation detail, not a JSON contract; these fields preserve the existing clients' response shape without relying on its bean properties. New APIs use Spring Data's PagedModel. properties: content: type: array items: $ref: "#/components/schemas/AuthEventView" empty: type: boolean first: type: boolean last: type: boolean number: type: integer format: int32 numberOfElements: type: integer format: int32 pageable: $ref: "#/components/schemas/Pageable" size: type: integer format: int32 sort: $ref: "#/components/schemas/Sort" totalElements: type: integer format: int64 totalPages: type: integer format: int32 PageResponseDTOConfigAuditEntryView: type: object description: |- Stable wire representation for the APIs that expose flat page metadata. Spring Data's PageImpl is an implementation detail, not a JSON contract; these fields preserve the existing clients' response shape without relying on its bean properties. New APIs use Spring Data's PagedModel. properties: content: type: array items: $ref: "#/components/schemas/ConfigAuditEntryView" empty: type: boolean first: type: boolean last: type: boolean number: type: integer format: int32 numberOfElements: type: integer format: int32 pageable: $ref: "#/components/schemas/Pageable" size: type: integer format: int32 sort: $ref: "#/components/schemas/Sort" totalElements: type: integer format: int64 totalPages: type: integer format: int32 PageResponseDTOObservationList: type: object description: |- Stable wire representation for the APIs that expose flat page metadata. Spring Data's PageImpl is an implementation detail, not a JSON contract; these fields preserve the existing clients' response shape without relying on its bean properties. New APIs use Spring Data's PagedModel. properties: content: type: array items: $ref: "#/components/schemas/ObservationList" empty: type: boolean first: type: boolean last: type: boolean number: type: integer format: int32 numberOfElements: type: integer format: int32 pageable: $ref: "#/components/schemas/Pageable" size: type: integer format: int32 sort: $ref: "#/components/schemas/Sort" totalElements: type: integer format: int64 totalPages: type: integer format: int32 PageResponseDTOSyncJob: type: object description: |- Stable wire representation for the APIs that expose flat page metadata. Spring Data's PageImpl is an implementation detail, not a JSON contract; these fields preserve the existing clients' response shape without relying on its bean properties. New APIs use Spring Data's PagedModel. properties: content: type: array items: $ref: "#/components/schemas/SyncJob" empty: type: boolean first: type: boolean last: type: boolean number: type: integer format: int32 numberOfElements: type: integer format: int32 pageable: $ref: "#/components/schemas/Pageable" size: type: integer format: int32 sort: $ref: "#/components/schemas/Sort" totalElements: type: integer format: int64 totalPages: type: integer format: int32 PageResponseDTOUserViewUser: type: object description: |- Stable wire representation for the APIs that expose flat page metadata. Spring Data's PageImpl is an implementation detail, not a JSON contract; these fields preserve the existing clients' response shape without relying on its bean properties. New APIs use Spring Data's PagedModel. properties: content: type: array items: $ref: "#/components/schemas/UserViewUser" empty: type: boolean first: type: boolean last: type: boolean number: type: integer format: int32 numberOfElements: type: integer format: int32 pageable: $ref: "#/components/schemas/Pageable" size: type: integer format: int32 sort: $ref: "#/components/schemas/Sort" totalElements: type: integer format: int64 totalPages: type: integer format: int32 Pageable: type: object properties: offset: type: integer format: int64 pageNumber: type: integer format: int32 pageSize: type: integer format: int32 paged: type: boolean sort: $ref: "#/components/schemas/Sort" unpaged: type: boolean PagedModelFeedbackItem: type: object properties: content: type: array items: $ref: "#/components/schemas/FeedbackItem" page: $ref: "#/components/schemas/PageMetadata" PagedModelReviewFeedback: type: object properties: content: type: array items: $ref: "#/components/schemas/ReviewFeedback" page: $ref: "#/components/schemas/PageMetadata" PagedModelReviewObservation: type: object properties: content: type: array items: $ref: "#/components/schemas/ReviewObservation" page: $ref: "#/components/schemas/PageMetadata" PagedModelReviewRunSummary: type: object properties: content: type: array items: $ref: "#/components/schemas/ReviewRunSummary" page: $ref: "#/components/schemas/PageMetadata" PagedModelSurvey: type: object properties: content: type: array items: $ref: "#/components/schemas/Survey" page: $ref: "#/components/schemas/PageMetadata" PagedModelSurveyResponse: type: object properties: content: type: array items: $ref: "#/components/schemas/SurveyResponse" page: $ref: "#/components/schemas/PageMetadata" PagedModelTracedArtifact: type: object properties: content: type: array items: $ref: "#/components/schemas/TracedArtifact" page: $ref: "#/components/schemas/PageMetadata" ParticipationCounts: type: object properties: declined: type: integer format: int64 invited: type: integer format: int64 description: "every account shown the invitation, including those who then\ \ responded or declined" responded: type: integer format: int64 required: - declined - invited - responded PersonDataProvider: type: object properties: id: type: integer format: int64 serverUrl: type: string type: type: string required: - id - serverUrl - type PersonDataRequest: type: object properties: completed: type: object additionalProperties: type: integer format: int64 counts: type: object additionalProperties: type: integer format: int64 expiresAt: type: string format: date-time externalDeliveries: type: array items: $ref: "#/components/schemas/ExternalDelivery" failureCode: type: string id: type: string format: uuid scope: $ref: "#/components/schemas/PersonDataScope" state: type: string enum: - PREVIEW - ERASING - FAILED - COMPLETE - EXPIRED required: - completed - counts - expiresAt - externalDeliveries - id - state PersonDataScope: type: object properties: accountId: type: integer format: int64 identities: type: array items: $ref: "#/components/schemas/Identity" required: - identities PlacePracticeRequest: type: object description: A practice's position in the catalog properties: groupSlug: type: string description: Destination group slug; omit to place the practice in Unassigned example: review-ready-work position: type: integer format: int32 description: Zero-based position in the destination example: 1 minimum: 0 required: - position Practice: type: object description: Practice definition for evaluating developer contributions properties: artifactKind: type: string description: "Kind of work this practice reviews, read off its signals" example: scm.pull_request automatedReviewPolicy: $ref: "#/components/schemas/PracticeAutomatedReviewPolicy" automatedReviewValidation: $ref: "#/components/schemas/PracticeAutomatedReviewValidation" automatedReviewWithdrawal: $ref: "#/components/schemas/PracticeEvidenceLimitation" description: "Why Hephaestus never reviews this practice whatever its own\ \ policy says: the catalogue entry it was copied from withdrew automated\ \ review. Absent when its own policy decides." autonomy: $ref: "#/components/schemas/AutonomyAssignment" description: "How much autonomy the system has over this practice, whether\ \ that was set here or inherited from its group or workspace, and which\ \ level decided it" catalogOrigin: $ref: "#/components/schemas/CatalogOrigin" createdAt: type: string format: date-time description: Timestamp when the practice was created criteria: type: string description: Practice review criteria deliveryBehavior: $ref: "#/components/schemas/PracticeDeliveryBehavior" displayOrder: type: integer format: int32 description: Position within its group (lowest first); ties broken by name evidenceRequirements: type: array items: $ref: "#/components/schemas/PracticeEvidenceRequirement" groupSlug: type: string description: "Slug of the practice group this practice is bound to, if any" id: type: integer format: int64 description: Practice ID name: type: string description: Human-readable name precomputeScript: type: string description: TypeScript/Node precompute script for static analysis before AI review precondition: $ref: "#/components/schemas/PracticePrecondition" reviewWhen: type: object additionalProperties: type: array items: type: string uniqueItems: true description: Automatic review state selections. An empty object imposes no state restrictions. Each selected dimension requires a nonempty set of non-null values offered by the work type descriptor. Values within a dimension are alternatives; all selected dimensions must match. signals: type: array description: Signals that start a practice review items: type: string slug: type: string description: URL-safe identifier unique within workspace subject: type: string enum: - AUTHOR - ASSIGNEE - REVIEWER - MERGER updatedAt: type: string format: date-time description: Timestamp when the practice was last updated whatGoodLooksLike: type: string description: Developer-facing exemplar (developer layer) whyItMatters: type: string description: Developer-facing rationale (developer layer) required: - artifactKind - automatedReviewPolicy - automatedReviewValidation - autonomy - createdAt - criteria - deliveryBehavior - displayOrder - evidenceRequirements - id - name - reviewWhen - signals - slug - subject - updatedAt PracticeAutomatedReview: type: object additionalProperties: false description: Author-declared automated review and evidence sufficiency for one practice properties: evidenceSufficiency: type: string description: Whether meeting every evidence requirement provides enough context to review the work enum: - SUFFICIENT_WHEN_REQUIREMENTS_MET - DECLARED_EVIDENCE_INSUFFICIENT - NONE mode: type: string description: Implementation Hephaestus uses for automated review enum: - LANGUAGE_MODEL - NONE required: - evidenceSufficiency - mode PracticeAutomatedReviewPolicy: type: object additionalProperties: false description: Author-defined automated review settings for one practice revision properties: automatedReview: $ref: "#/components/schemas/PracticeAutomatedReview" description: Automated review configuration; human review is a separate process insufficiencyReason: $ref: "#/components/schemas/PracticeEvidenceLimitation" description: Why this practice needs a human rather than automated review; present only when evidenceSufficiency is DECLARED_EVIDENCE_INSUFFICIENT knownLimitations: type: array description: Claims the selected evidence cannot support even when every requirement passes items: $ref: "#/components/schemas/PracticeEvidenceLimitation" sourceContractVersion: type: string description: Exact contract version that defines source kinds and source-state semantics whenEvidenceIsInsufficient: type: string description: Conservative action when required evidence does not pass enum: - SKIP_AUTOMATED_REVIEW required: - automatedReview - knownLimitations - sourceContractVersion - whenEvidenceIsInsufficient PracticeAutomatedReviewValidation: type: object description: "Who stands behind a practice's automated-review policy, and which\ \ exact policy" properties: policyDigest: type: string description: SHA-256 digest of the exact automated-review policy reviewRuleFingerprint: type: string description: Versioned fingerprint of the exact review rules sourceContractVersion: type: string description: Source contract the declared practice definition is written against status: type: string description: Validation lifecycle; authors cannot mark their own review policy as independently validated enum: - AUTHOR_DECLARED required: - policyDigest - reviewRuleFingerprint - sourceContractVersion - status PracticeDefinition: type: object additionalProperties: false description: The authored standard and the occasion on which it is reviewed. properties: automatedReviewPolicy: $ref: "#/components/schemas/PracticeAutomatedReviewPolicy" criteria: type: string deliveryBehavior: $ref: "#/components/schemas/PracticeDeliveryBehavior" evidenceRequirements: type: array items: $ref: "#/components/schemas/PracticeEvidenceRequirement" groupSlug: type: string name: type: string precomputeScript: type: string precondition: $ref: "#/components/schemas/PracticePrecondition" reviewWhen: type: object additionalProperties: type: array items: type: string uniqueItems: true description: Automatic review state selections. An empty object imposes no state restrictions. Each selected dimension requires a nonempty set of non-null values offered by the work type descriptor. Values within a dimension are alternatives; all selected dimensions must match. signals: type: array items: type: string subject: type: string enum: - AUTHOR - ASSIGNEE - REVIEWER - MERGER whatGoodLooksLike: type: string whyItMatters: type: string required: - automatedReviewPolicy - criteria - deliveryBehavior - evidenceRequirements - name - reviewWhen - signals - subject PracticeDefinitionOptions: type: object description: "What a practice author may choose, per type of reviewed work" properties: sourceContractVersion: type: string description: Source contract these options describe example: 1.3.0 workTypes: type: array items: $ref: "#/components/schemas/PracticeWorkTypeDefinitionOptions" required: - sourceContractVersion - workTypes PracticeDeliveryBehavior: type: object additionalProperties: false description: "Delivery choices declared by the practice author, not inferred\ \ from its slug." properties: overlapGroup: type: string redundantToSlug: type: string summaryOnly: type: boolean required: - summaryOnly PracticeEvidenceBlocker: type: object description: "One thing that blocked automated review, and how many reviews\ \ it affected" properties: reasonCode: type: string description: Readiness reason recorded for that source or practice enum: - SOURCE_NOT_AVAILABLE - SOURCE_INCOMPLETE - SOURCE_EMPTY - NO_AUTOMATED_REVIEW - DECLARED_EVIDENCE_INSUFFICIENT - SUBJECT_NOT_IN_THE_WORK reviewsAffected: type: integer format: int32 description: Reviews this blocker affected sourceKind: type: string description: Source that did not meet its requirement; absent when the practice itself runs no review required: - reasonCode - reviewsAffected PracticeEvidenceLimitation: type: object additionalProperties: false description: Known claim that the selected evidence cannot support even when every requirement passes properties: code: type: string description: Stable machine-readable identifier example: RUNTIME_BEHAVIOR_NOT_OBSERVED pattern: "[A-Z][A-Z0-9_]{2,63}" description: type: string description: Plain-language explanation of the claim the evidence cannot support maxLength: 500 minLength: 1 required: - code - description PracticeEvidenceOutcome: type: object description: Recent review readiness for one practice's evidence requirements properties: blockersObserved: type: array description: "Blockers seen on the skipped reviews, most frequent first" items: $ref: "#/components/schemas/PracticeEvidenceBlocker" consideredReviews: type: integer format: int32 description: Reviews that considered this practice practiceSlug: type: string description: Practice this outcome describes reviewedCount: type: integer format: int32 description: Reviews where the evidence met every requirement required: - blockersObserved - consideredReviews - practiceSlug - reviewedCount PracticeEvidenceRequirement: type: object additionalProperties: false description: A source a practice reads and the stance it takes towards it properties: sourceKind: type: string description: Stable source identifier from the selected source contract stance: type: string description: Whether an absent or degraded capture refuses the review enum: - REQUIRED - EXHAUSTIVE - CONTEXTUAL required: - sourceKind - stance PracticeEvidenceSourceOption: type: object description: An evidence source a practice on this kind of work may read properties: description: type: string displayName: type: string privacyClass: type: string enum: - INTERNAL - PERSONAL - SENSITIVE_PERSONAL requiredQuality: type: string description: What requiring this source demands of its capture; fixed by the source contract enum: - ANY_CAPTURE - COMPLETE - COMPLETE_AND_NON_EMPTY selectionScope: type: string description: "How much of the source one capture takes, and the bound past\ \ which it is no longer whole" sourceKind: type: string supportsExhaustiveEvidence: type: boolean description: "Whether this source can be captured whole, and so whether\ \ a practice may rest a claim about what is absent from it on the capture" required: - description - displayName - privacyClass - requiredQuality - selectionScope - sourceKind - supportsExhaustiveEvidence PracticeFact: type: object properties: autonomy: type: string enum: - "OFF" - HUMAN_APPROVAL - AUTOMATIC slug: type: string PracticeGroup: type: object description: A practice group grouping related practices into a learning objective properties: autonomy: $ref: "#/components/schemas/AutonomyAssignment" description: "How much autonomy the system has over every practice in this\ \ group that holds no autonomy of its own, whether that was set here or\ \ inherited from the workspace, and which level decided it" catalogOrigin: $ref: "#/components/schemas/CatalogOrigin" color: type: string description: Optional palette colour key for the group's chip createdAt: type: string format: date-time description: Timestamp when the group was created description: type: string description: What this group develops displayOrder: type: integer format: int32 description: Sort order within the workspace icon: type: string description: Optional lucide icon name for the group's chip id: type: integer format: int64 description: Group ID name: type: string description: Human-readable name slug: type: string description: URL-safe identifier unique within the workspace updatedAt: type: string format: date-time description: Timestamp when the group was last updated visibleInPracticeDashboards: type: boolean description: Whether this group is shown in practice dashboards required: - autonomy - createdAt - displayOrder - id - name - slug - visibleInPracticeDashboards PracticeGroupReviewRun: type: object description: A complete review run in a developer's practice-group history properties: observations: type: array description: "Every visible observation of the run, complete enough to open\ \ in place" items: $ref: "#/components/schemas/ObservationDetail" reviewId: type: string format: uuid reviewedAt: type: string format: date-time reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" required: - observations - reviewId - reviewedAt - reviewedWork PracticeGroupReviewRunsPage: type: object description: A page of visible review runs properties: content: type: array items: $ref: "#/components/schemas/PracticeGroupReviewRun" hasNext: type: boolean page: type: integer format: int32 size: type: integer format: int32 required: - content PracticeGroupStanding: type: object description: A developer's derived qualitative standing for one Group including 1<=nstatus\ \ is FAILED" enum: - RATE_LIMITED - UNAVAILABLE - MALFORMED history: type: array description: "the releases this instance ran, newest first" items: $ref: "#/components/schemas/ReleaseStart" lastAttempt: type: string format: date-time description: "when a check was last started, on any outcome" lastSuccess: type: string format: date-time description: "when a check last completed, which is when latest\ \ was observed" latest: $ref: "#/components/schemas/LatestRelease" description: the newest published release as of lastSuccess nextCheck: type: string format: date-time description: when the next automatic check is due retryUntil: type: string format: date-time description: the wait GitHub named on a rate limit; a manual check before it is refused running: $ref: "#/components/schemas/RunningRelease" description: the identity this process reports runningSince: type: string format: date-time description: "when this instance started the running release, absent unless\ \ the newest start is it" status: type: string description: the verdict an administrator reads first enum: - DISABLED - NOT_APPLICABLE - NEVER_CHECKED - CURRENT - UPDATE_AVAILABLE - FAILED required: - history - running - status RenameWorkspaceSlugRequest: type: object description: Request to rename a workspace's URL slug properties: newSlug: type: string description: Non-reserved lowercase ASCII DNS label. Consecutive hyphens are prohibited. example: new-workspace-slug maxLength: 51 minLength: 3 pattern: "^(?!.*--)[a-z0-9][a-z0-9-]{1,49}[a-z0-9]$" required: - newSlug ReorderPracticeGroupsRequest: type: object description: Reorder practice groups to match the supplied list properties: orderedSlugs: type: array description: Group slugs in the desired display order example: - review-ready-work - acting-on-review-feedback items: type: string minItems: 1 required: - orderedSlugs ReorderPracticesRequest: type: object description: Reorder one group's practices to match the supplied list properties: groupSlug: type: - string - "null" description: Slug of the group whose practices are being reordered; null reorders the unassigned bucket example: review-ready-work orderedSlugs: type: array description: Practice slugs in the desired display order — the complete set for the group example: - describe-what-and-why - ready-and-traceable-handoff items: type: string minItems: 1 required: - orderedSlugs RepositoryInfo: type: object description: Information about a git repository properties: description: type: string description: Description of the repository hiddenFromContributions: type: boolean description: Whether activity in this repository is left out of a team's activity htmlUrl: type: string description: URL to the repository on the git provider id: type: integer format: int64 description: Unique identifier of the repository labels: type: array description: Labels defined in the repository items: $ref: "#/components/schemas/LabelInfo" name: type: string description: Name of the repository nameWithOwner: type: string description: "Full name including owner (e.g., 'owner/repo')" required: - hiddenFromContributions - htmlUrl - id - name - nameWithOwner ResearchConsent: type: object properties: granted: type: boolean noticeVersion: type: string researchOrganization: type: string description: The organization this control named on screen required: - granted - noticeVersion ResourceCounts: type: object description: Resource-level rollup for the connection overview badge properties: errored: type: integer format: int64 description: Resources currently reporting a sync error pending: type: integer format: int64 description: "Resources that have never completed a sync (no lastSyncedAt).\ \ Defined on the timestamp rather than on a provider's status vocabulary\ \ so it means the same thing for a repository, a Slack channel and an\ \ Outline collection." stale: type: integer format: int64 description: "Resources whose last sync is older than twice the connection's\ \ scheduled cadence. Always 0 when the cadence is unknown or the schedule\ \ is irregular — staleness is a judgement against a known cron, and without\ \ one this declines to guess rather than flagging healthy resources." total: type: integer format: int64 description: Total resources known to this connection required: - errored - pending - stale - total ReviewBackfillRun: type: object description: "A campaign as an admin sees it — before confirming, while it runs,\ \ and after it ends." properties: artifactKind: type: string confirmedByAccountId: type: integer format: int64 description: Who authorised the spend; absent until the run is confirmed createdAt: type: string format: date-time discoveredVia: type: string description: "BACKFILL for a campaign an admin scoped by hand, SWEEP for\ \ one a recurring schedule opened" enum: - EVENT - SYNC - MANUAL - BACKFILL - SWEEP estimatedArtifacts: type: integer format: int32 estimatedCostUsd: type: number format: decimal description: Forecast total spend in USD; absent when the workspace has no priced review history failedCount: type: integer format: int32 description: |- artifacts whose submission threw, leaving no job and no recorded decision. Non-zero means this campaign's baseline has holes in it, which is why it is reported apart from a pass. finishedAt: type: string format: date-time fromAt: type: string format: date-time id: type: string format: uuid passedCount: type: integer format: int32 description: |- artifacts walked past without one: already measured at their current state, or refused by the review gate. The campaign looked at each of these and decided. pauseReason: type: string description: Set only while the run is PAUSED enum: - BUDGET_EXHAUSTED - REVIEW_MODEL_UNBOUND - WORKSPACE_UNAVAILABLE requestedByAccountId: type: integer format: int64 startedAt: type: string format: date-time status: type: string enum: - AWAITING_CONFIRMATION - RUNNING - PAUSED - COMPLETED - CANCELLED submittedCount: type: integer format: int32 description: artifacts for which a review job was created sweepScheduleId: type: string format: uuid description: The schedule that opened this run; absent for a campaign an admin scoped by hand toAt: type: string format: date-time required: - artifactKind - createdAt - discoveredVia - estimatedArtifacts - failedCount - fromAt - id - passedCount - requestedByAccountId - status - submittedCount - toAt ReviewBoundFeedback: type: object description: Feedback composed from an observation properties: agentJobId: type: string format: uuid channel: type: string enum: - IN_CONTEXT - IN_CHAT - IN_APP createdAt: type: string format: date-time deliveredAt: type: string format: date-time description: When the message was placed; null if it was not delivered deliveryState: type: string enum: - AWAITING_APPROVAL - PREPARED - PARTIALLY_DELIVERED - PARTIALLY_FAILED - DELIVERED - SUPERSEDED - SUPPRESSED - FAILED - DISCARDED - UNCONFIRMED feedbackId: type: string format: uuid role: type: string description: Whether the observation led the feedback or reinforced it enum: - PRIMARY - SUPPORTING suppressionReason: type: string description: Why delivery stopped; set on withheld or terminally partial feedback enum: - VOLUME_CAPPED - COMPOSER_DEDUPED - COMPOSER_WITHHELD - REPEATS_DELIVERED_NOTE - REACTED_DISPUTED - REACTED_NOT_APPLICABLE - CONVERSATION_EXPIRED - ARTIFACT_GONE - ARTIFACT_CLOSED - ISSUE_SNAPSHOT_CHANGED - ARTIFACT_MERGED - PUBLIC_SUBJECT_INELIGIBLE - ARTIFACT_DRAFT - RECIPIENT_OPTED_OUT - EMPTY_AFTER_SANITIZE - INSTANCE_SILENCED - WORKSPACE_DISABLED - WORKSPACE_DELIVERY_PAUSED - STALE_ROLLOUT_REVISION - OUTSIDE_CURRENT_COVERAGE - APPROVAL_STALE - APPROVAL_NO_LONGER_ELIGIBLE - PRACTICE_REQUIRES_APPROVAL - BACKFILL_QUIET - OBSERVATION_INVALIDATED - REVIEWED_REVISION_CHANGED required: - agentJobId - channel - createdAt - deliveryState - feedbackId - role ReviewBoundObservation: type: object description: An observation that contributed to a piece of feedback properties: claimCurrentness: type: string description: "Whether an observation's claim still stands: its practice's\ \ review rules are unchanged and it was not superseded, which an issue's\ \ observations are when a change to its reviewable content is recorded.\ \ It says neither whether a later review ran nor whether the work changed\ \ since it was reviewed. Earlier observation standards and missing fingerprints\ \ are unverifiable under the current whole-practice standard" enum: - CURRENT - STALE - UNVERIFIABLE group: $ref: "#/components/schemas/ReviewPracticeGroup" description: Practice group; null when the practice is Unassigned observationId: type: string format: uuid observedAt: type: string format: date-time ordinal: type: integer format: int32 description: Render order within the feedback (lower renders earlier) outcome: type: string description: Result of the practice review enum: - MET - NOT_MET - NOT_APPLICABLE - UNDETERMINED practiceName: type: string practiceSlug: type: string role: type: string description: Whether the observation leads the feedback or reinforces it enum: - PRIMARY - SUPPORTING severity: type: string description: Severity band (null unless outcome is NOT_MET) enum: - CRITICAL - MAJOR - MINOR - INFO summary: type: string required: - claimCurrentness - observationId - observedAt - ordinal - outcome - practiceName - practiceSlug - role - summary ReviewContext: type: object description: "The piece of reviewed work a provider page shows, and what the\ \ caller may do about it" properties: canInspectReviewDetails: type: boolean description: "Whether the caller may read the review details behind this\ \ work — the runs, observations and the delivery of each piece of feedback\ \ — which is a workspace admin's view" canRequestReview: type: boolean description: "Whether the caller may ask for a review of this work: they\ \ are its author or an assignee, or a workspace admin, through one of\ \ their own linked accounts. It does not promise a review starts; the\ \ answer to the ask says whether one did, and why not" work: $ref: "#/components/schemas/ReviewedWorkRef" description: "The work as this workspace mirrored it; its id and kind address\ \ the trace, observations and feedback about it" required: - canInspectReviewDetails - canRequestReview - work ReviewFeedback: type: object properties: agentJobId: type: string format: uuid bodyPreview: type: string description: Leading characters of the composed body; null when the feedback carries no body bodyTruncated: type: boolean channel: type: string enum: - IN_CONTEXT - IN_CHAT - IN_APP createdAt: type: string format: date-time deliveredAt: type: string format: date-time description: When the feedback was placed; null if it was not delivered deliveryState: type: string enum: - AWAITING_APPROVAL - PREPARED - PARTIALLY_DELIVERED - PARTIALLY_FAILED - DELIVERED - SUPERSEDED - SUPPRESSED - FAILED - DISCARDED - UNCONFIRMED id: type: string format: uuid observationCount: type: integer format: int64 description: Number of observations used to compose the feedback recipient: $ref: "#/components/schemas/ReviewSubject" description: Who the feedback is addressed to; null when the identity is no longer resolvable replacesId: type: string format: uuid description: The feedback this one replaced; null on a first delivery reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" description: Reviewed work the feedback targets; null when it is unanchored subject: $ref: "#/components/schemas/ReviewSubject" description: Whose work the feedback addresses; may equal the recipient suppressionReason: type: string description: Why delivery stopped; set on withheld or terminally partial feedback enum: - VOLUME_CAPPED - COMPOSER_DEDUPED - COMPOSER_WITHHELD - REPEATS_DELIVERED_NOTE - REACTED_DISPUTED - REACTED_NOT_APPLICABLE - CONVERSATION_EXPIRED - ARTIFACT_GONE - ARTIFACT_CLOSED - ISSUE_SNAPSHOT_CHANGED - ARTIFACT_MERGED - PUBLIC_SUBJECT_INELIGIBLE - ARTIFACT_DRAFT - RECIPIENT_OPTED_OUT - EMPTY_AFTER_SANITIZE - INSTANCE_SILENCED - WORKSPACE_DISABLED - WORKSPACE_DELIVERY_PAUSED - STALE_ROLLOUT_REVISION - OUTSIDE_CURRENT_COVERAGE - APPROVAL_STALE - APPROVAL_NO_LONGER_ELIGIBLE - PRACTICE_REQUIRES_APPROVAL - BACKFILL_QUIET - OBSERVATION_INVALIDATED - REVIEWED_REVISION_CHANGED required: - agentJobId - bodyTruncated - channel - createdAt - deliveryState - id - observationCount ReviewFeedbackCounts: type: object description: "Counts of feedback, one per delivery state" properties: awaitingApproval: type: integer format: int64 description: "AWAITING_APPROVAL: waiting for an admin to approve or reject\ \ it" delivered: type: integer format: int64 description: "DELIVERED: delivered where it was meant to appear" discarded: type: integer format: int64 description: "DISCARDED: an admin rejected it instead of approving it; it\ \ is never delivered" failed: type: integer format: int64 description: "FAILED: delivery failed" partiallyDelivered: type: integer format: int64 description: "PARTIALLY_DELIVERED: some of its placements delivered, the\ \ rest still to deliver or suppressed" partiallyFailed: type: integer format: int64 description: "PARTIALLY_FAILED: delivery failed after some of its placements\ \ were delivered" prepared: type: integer format: int64 description: "PREPARED: ready to deliver and not delivered yet" superseded: type: integer format: int64 description: "SUPERSEDED: replaced by newer feedback" suppressed: type: integer format: int64 description: "SUPPRESSED: Hephaestus refused to deliver it, with a suppression\ \ reason" unconfirmed: type: integer format: int64 description: "UNCONFIRMED: a conversation linked it with no record that\ \ it was shown, so it counts as neither delivered nor suppressed" required: - awaitingApproval - delivered - discarded - failed - partiallyDelivered - partiallyFailed - prepared - superseded - suppressed - unconfirmed ReviewFeedbackDetail: type: object description: Full feedback detail including the stored composed body properties: agentJobId: type: string format: uuid approval: $ref: "#/components/schemas/FeedbackApproval" description: "Immutable human decision for this proposal, when one has been\ \ made" body: type: string description: "Stored composed body; null when none was produced, and always\ \ null on the IN_APP and IN_CHAT channels — neither the developer's practice\ \ pages nor the mentor's prepared context is readable by an operator" channel: type: string enum: - IN_CONTEXT - IN_CHAT - IN_APP createdAt: type: string format: date-time deliveredAt: type: string format: date-time description: When the feedback was placed; null if it was not delivered deliveryPolicy: type: array description: Ordered delivery-policy evaluations for this feedback's review items: $ref: "#/components/schemas/DeliveryPolicyTrace" deliveryState: type: string enum: - AWAITING_APPROVAL - PREPARED - PARTIALLY_DELIVERED - PARTIALLY_FAILED - DELIVERED - SUPERSEDED - SUPPRESSED - FAILED - DISCARDED - UNCONFIRMED dispute: $ref: "#/components/schemas/FeedbackDispute" description: The developer's standing dispute of this feedback; null while they do not dispute it id: type: string format: uuid observations: type: array description: Source observations in render order items: $ref: "#/components/schemas/ReviewBoundObservation" placements: type: array description: Recorded placements; empty when none items: $ref: "#/components/schemas/ReviewPlacement" proposedPlacements: type: array description: Exact ordered summary and inline messages covered by the approval decision items: $ref: "#/components/schemas/ReviewProposedPlacement" recipient: $ref: "#/components/schemas/ReviewSubject" description: Who the feedback is addressed to; null when the identity is no longer resolvable replacesId: type: string format: uuid description: The feedback this one replaced; null on a first delivery reviewedRevision: type: string description: Reviewed source revision for an immutable approval package reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" description: Reviewed work the feedback targets; null when it is unanchored subject: $ref: "#/components/schemas/ReviewSubject" description: Whose work the feedback addresses; may equal the recipient suppressionReason: type: string description: Why delivery stopped; set on withheld or terminally partial feedback enum: - VOLUME_CAPPED - COMPOSER_DEDUPED - COMPOSER_WITHHELD - REPEATS_DELIVERED_NOTE - REACTED_DISPUTED - REACTED_NOT_APPLICABLE - CONVERSATION_EXPIRED - ARTIFACT_GONE - ARTIFACT_CLOSED - ISSUE_SNAPSHOT_CHANGED - ARTIFACT_MERGED - PUBLIC_SUBJECT_INELIGIBLE - ARTIFACT_DRAFT - RECIPIENT_OPTED_OUT - EMPTY_AFTER_SANITIZE - INSTANCE_SILENCED - WORKSPACE_DISABLED - WORKSPACE_DELIVERY_PAUSED - STALE_ROLLOUT_REVISION - OUTSIDE_CURRENT_COVERAGE - APPROVAL_STALE - APPROVAL_NO_LONGER_ELIGIBLE - PRACTICE_REQUIRES_APPROVAL - BACKFILL_QUIET - OBSERVATION_INVALIDATED - REVIEWED_REVISION_CHANGED threadKey: type: string description: Cross-run continuity key tying successive deliveries together withdrawals: type: array description: "Every withdrawal of this card from the developer's practice\ \ page, newest first; empty when none" items: $ref: "#/components/schemas/FeedbackWithdrawal" required: - agentJobId - channel - createdAt - deliveryPolicy - deliveryState - id - observations - placements - proposedPlacements - withdrawals ReviewObservation: type: object description: A practice review observation with its linked feedback outcomes properties: agentJobId: type: string format: uuid claimCurrentness: type: string description: "Whether an observation's claim still stands: its practice's\ \ review rules are unchanged and it was not superseded, which an issue's\ \ observations are when a change to its reviewable content is recorded.\ \ It says neither whether a later review ran nor whether the work changed\ \ since it was reviewed. Earlier observation standards and missing fingerprints\ \ are unverifiable under the current whole-practice standard" enum: - CURRENT - STALE - UNVERIFIABLE disputedAt: type: string format: date-time description: When the developer last disputed feedback written from this observation; null while nothing about it is disputed feedback: $ref: "#/components/schemas/ReviewFeedbackCounts" description: Counts of linked feedback by delivery state group: $ref: "#/components/schemas/ReviewPracticeGroup" description: Practice group; null when the practice is Unassigned id: type: string format: uuid invalidatedAt: type: string format: date-time description: When a workspace admin invalidated this observation; null while it stands observedAt: type: string format: date-time origin: type: string description: "What occasioned the measurement. BACKFILL came from a confirmed\ \ campaign over work that already existed, so it is not a point on the\ \ live trend line." enum: - LIVE - MANUAL - BACKFILL outcome: type: string description: Result of the practice review enum: - MET - NOT_MET - NOT_APPLICABLE - UNDETERMINED practiceName: type: string practiceSlug: type: string recurrenceKey: type: string description: Cross-run locus key; null when continuity is unavailable reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" severity: type: string description: Severity band (null unless outcome is NOT_MET) enum: - CRITICAL - MAJOR - MINOR - INFO subject: $ref: "#/components/schemas/ReviewSubject" description: Whose work the observation is about; null when the identity is no longer resolvable summary: type: string required: - agentJobId - claimCurrentness - feedback - id - observedAt - origin - outcome - practiceName - practiceSlug - reviewedWork - summary ReviewObservationCounts: type: object description: Counts of observations by assessment properties: met: type: integer format: int64 notApplicable: type: integer format: int64 description: Practices whose subject did not occur in this work notMet: type: integer format: int64 undetermined: type: integer format: int64 description: Practices that looked at the evidence and could not settle the question either way; reported apart from notApplicable because one says there was nothing here to judge and the other says we could not tell required: - met - notApplicable - notMet - undetermined ReviewObservationDetail: type: object description: An observation with evidence and linked feedback properties: agentJobId: type: string format: uuid claimCurrentness: type: string description: "Whether an observation's claim still stands: its practice's\ \ review rules are unchanged and it was not superseded, which an issue's\ \ observations are when a change to its reviewable content is recorded.\ \ It says neither whether a later review ran nor whether the work changed\ \ since it was reviewed. Earlier observation standards and missing fingerprints\ \ are unverifiable under the current whole-practice standard" enum: - CURRENT - STALE - UNVERIFIABLE disputes: type: array description: "The developer's standing disputes of feedback written from\ \ this observation, newest first; empty when nothing about it is disputed" items: $ref: "#/components/schemas/FeedbackDispute" evidence: $ref: "#/components/schemas/ObservationEvidence" evidenceRationale: type: string feedback: type: array description: "Linked feedback, newest first" items: $ref: "#/components/schemas/ReviewBoundFeedback" group: $ref: "#/components/schemas/ReviewPracticeGroup" description: Practice group; null when the practice is Unassigned id: type: string format: uuid invalidations: type: array description: "Every correction by a workspace admin, newest first; the first\ \ is in force while it has no restoration" items: $ref: "#/components/schemas/ObservationInvalidation" observedAt: type: string format: date-time outcome: type: string description: Result of the practice review enum: - MET - NOT_MET - NOT_APPLICABLE - UNDETERMINED practiceName: type: string practiceRevisionId: type: integer format: int64 description: "Criteria revision selected as of job start, when available" practiceSlug: type: string recurrenceKey: type: string description: Cross-run locus key; null when continuity is unavailable reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" severity: type: string description: Severity band (null unless outcome is NOT_MET) enum: - CRITICAL - MAJOR - MINOR - INFO subject: $ref: "#/components/schemas/ReviewSubject" description: Whose work the observation is about; null when the identity is no longer resolvable summary: type: string required: - agentJobId - claimCurrentness - disputes - feedback - id - invalidations - observedAt - outcome - practiceName - practiceSlug - reviewedWork - summary ReviewPlacement: type: object description: A recorded message placement properties: anchorEndLine: type: integer format: int32 description: Last anchored line (1-based) anchorKind: type: string description: Anchor granularity; null for non-inline placements enum: - LINE - RANGE - FILE - IMAGE anchorPath: type: string description: Head-side path of the anchored file anchorSide: type: string description: Diff side of the anchor enum: - OLD - NEW anchorStartLine: type: integer format: int32 description: First anchored line (1-based) chatMessageId: type: string format: uuid description: Mentor chat-message identifier id: type: string format: uuid placementType: type: string enum: - SUMMARY - INLINE - CONVERSATION_TURN - LOCATION_COMMENT postedCommentRef: type: string description: Provider-native comment identifier required: - id - placementType ReviewPracticeGroup: type: object properties: color: type: string description: Palette color key icon: type: string description: Lucide icon name name: type: string slug: type: string required: - name - slug ReviewPracticeOutcomes: type: object description: "What one run decided about each practice it observed for this\ \ developer against the practice's whole positive standard, one count per\ \ practice however many observations it recorded; an invalidated observation\ \ decides nothing, and a met or not-met outcome recorded under an earlier\ \ or missing assessment scheme counts as undetermined" properties: met: type: integer format: int32 description: Practices with at least one counted met outcome and none not met notApplicable: type: integer format: int32 description: Practices whose every counted outcome was not applicable notMet: type: integer format: int32 description: Practices with at least one counted not-met outcome undetermined: type: integer format: int32 description: "Practices the run could not settle: no counted met or not-met\ \ outcome, and not only not-applicable outcomes" required: - met - notApplicable - notMet - undetermined ReviewProposedPlacement: type: object description: One exact provider message included in a review awaiting approval properties: body: type: string endLine: type: integer format: int32 description: Last 1-based line; null for a single-line comment or summary path: type: string description: Head-side file path; null for the summary startLine: type: integer format: int32 description: First 1-based line; null for the summary type: type: string enum: - SUMMARY - INLINE - CONVERSATION_TURN - LOCATION_COMMENT required: - body - type ReviewRepositoryTarget: type: object properties: baseBranches: type: array description: Exact pull-request base branches to cover; empty covers every base branch items: type: string nameWithOwner: type: string description: "Exact provider repository name, including its owner" maxLength: 255 minLength: 0 required: - baseBranches - nameWithOwner ReviewRequestOutcome: type: object description: What came of asking for a review properties: jobId: type: string format: uuid description: The review that is now running; absent when none was started reason: type: string description: The controlled-vocabulary reason nothing was started; absent when a review was started enum: - GATE_SKIPPED - COOLDOWN_ACTIVE - REQUEST_COOLDOWN_ACTIVE - REQUESTER_QUOTA_EXHAUSTED - CONCURRENT_DUPLICATE - COALESCED - OUT_OF_REVIEW_SCOPE - BOT_AUTHOR - BOT_REVIEWER - STALE_ROLLOUT_REVISION - WORKSPACE_INACTIVE - PRACTICES_DISABLED - NO_ACTIVE_PRACTICE - REVIEW_MODEL_UNBOUND - MEMBER_AI_DECLINED - PERSON_DATA_ERASED - PRACTICE_AUTONOMY_OFF - BUDGET_EXHAUSTED - SUBJECT_UNLINKED - MERGE_ACTOR_UNAVAILABLE - MODEL_UNAVAILABLE - ARTIFACT_NOT_VISIBLE - PENDING_DEADLINE_EXCEEDED - ARTIFACT_GONE reasonDescription: type: string description: "The reason as one sentence for the person who asked. Render\ \ it verbatim: it is written next to the reason it explains so that every\ \ surface says the same thing, and a re-worded copy is how a screen and\ \ a support answer come to disagree." status: type: string description: "Whether a review is now running, or nothing was started" enum: - SUBMITTED - REFUSED required: - status ReviewRunCounts: type: object description: Counts of practice reviews by status properties: cancelled: type: integer format: int64 completed: type: integer format: int64 failed: type: integer format: int64 queued: type: integer format: int64 running: type: integer format: int64 timedOut: type: integer format: int64 required: - cancelled - completed - failed - queued - running - timedOut ReviewRunRef: type: object description: One review run on the developer's work properties: at: type: string format: date-time description: When the review recorded its newest observation about this developer reviewId: type: string format: uuid reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" description: The piece of work the run reviewed status: type: string description: Where the review stands; absent when the review itself is no longer on record enum: - IN_PROGRESS - COMPLETED - FAILED required: - at - reviewId - reviewedWork ReviewRunSummary: type: object description: A review run with observation and feedback outcome counts properties: createdAt: type: string format: date-time feedback: $ref: "#/components/schemas/ReviewFeedbackCounts" id: type: string format: uuid observations: $ref: "#/components/schemas/ReviewObservationCounts" resultProcessing: type: string description: "Result-processing status: null = not applicable, PENDING =\ \ awaiting processing, DELIVERED = processing finished, FAILED = processing\ \ error. Processing may include delivery; this status alone does not establish\ \ feedback publication." enum: - PENDING - DELIVERED - FAILED reviewOutcome: type: string enum: - REVIEWED - INSUFFICIENT_EVIDENCE - COALESCED - SUPERSEDED status: type: string enum: - QUEUED - RUNNING - COMPLETED - FAILED - TIMED_OUT - CANCELLED target: $ref: "#/components/schemas/ReviewRunTarget" required: - createdAt - feedback - id - observations - reviewOutcome - status - target ReviewRunTarget: type: object description: Work reviewed by an agent job properties: reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" description: The reviewed work as every surface names it; absent when the run recorded no work title: type: string description: "Heading the run is listed under, which a run without recorded\ \ work still needs" type: type: string required: - title - type ReviewSubject: type: object properties: avatarUrl: type: string id: type: integer format: int64 login: type: string description: Login on the source provider name: type: string description: "Display name, when known" required: - id - login ReviewSweepSchedule: type: object description: "A standing instruction to review recent work on a cadence, as\ \ an admin sees it." properties: artifactKind: type: string cadence: type: string enum: - DAILY - WEEKLY createdAt: type: string format: date-time createdByAccountId: type: integer format: int64 enabled: type: boolean id: type: string format: uuid lastRunAt: type: string format: date-time description: When a campaign was last opened from this schedule; absent until the first one lookbackDays: type: integer format: int32 description: |- how far back each sweep looks. Bounded at write time to twice the cadence and never more than a week, which is what keeps a sweep's observations admissible in the same trend line as reviews that events triggered. nextRunAt: type: string format: date-time description: |- when the next sweep is due. Shown because it is the only way to tell a schedule that is working from one whose workspace has been skipping it. required: - artifactKind - cadence - createdAt - createdByAccountId - enabled - id - lookbackDays - nextRunAt ReviewedPractice: type: object description: Developer-facing view of a practice — criteria absent by construction properties: groupSlug: type: string description: "Slug of the practice group this belongs to, if any" name: type: string description: Human-readable name slug: type: string description: URL-safe identifier whatGoodLooksLike: type: string description: A concrete picture of doing this well whyItMatters: type: string description: "Why this practice matters, in plain language" required: - name - slug ReviewedWorkRef: type: object description: "A piece of reviewed work as every surface names it: enough to\ \ print a link" properties: container: type: string description: "Where the work sits, by name: a pull request's or an issue's\ \ repository, a document's collection; a conversation's channel is its\ \ label" id: type: string description: Identifier of the work within its kind kind: type: string description: Artifact kind id label: type: string description: "Short label the page prints: \"#22\", \"!425\", \"#backend-review\"\ \ or a document title" provider: type: string description: "The provider the work lives at, which decides its noun: a\ \ GitLab scm.pull_request is a merge request; absent when the run that\ \ named the work is gone" enum: - GITHUB - GITLAB - SLACK - OUTLINE title: type: string description: "The work's own title where the label does not already say\ \ it: a pull request's or an issue's; a conversation thread has none and\ \ a document's is its label" url: type: string description: "The work's page at its provider, when the provider exposes\ \ one" required: - id - kind - label Reviewer: type: object description: "Someone reviewing a pull request, and where their review stands" properties: state: type: string description: "REQUESTED while a review is asked of them, otherwise the verdict\ \ of their latest review that was not dismissed" enum: - CHANGES_REQUESTED - APPROVED - COMMENTED - REQUESTED user: $ref: "#/components/schemas/UserInfo" description: The reviewer required: - state - user RevokeSessionsResult: type: object properties: revoked: type: integer format: int32 required: - revoked RunningRelease: type: object description: |- Deployment-reported identity: the values the verified lock env handed this process, not an observation of the container. commit and image are absent outside a lock-driven deployment. properties: channel: type: string description: what kind of build that version names enum: - RELEASE - COMMIT - DEVELOPMENT commit: type: string description: the source commit the lock names environment: type: string description: the name the deployment gives this instance image: type: string description: the digest reference this container was started from roles: type: array description: the runtime roles this process booted with items: type: string enum: - SERVER - WORKER - WEBHOOK version: type: string description: the version the deployment passed as APP_VERSION required: - channel - environment - roles - version SessionView: type: object properties: client: type: string description: what signed in enum: - WEB - BROWSER_EXTENSION current: type: boolean expiresAt: type: string format: date-time description: "when the token expires; for an installed client, the session's\ \ own deadline" ip: type: string issuedAt: type: string format: date-time jti: type: string format: uuid userAgent: type: string required: - client - current - expiresAt - jti SlackChannelCandidate: type: object description: A Slack channel the app can offer in the workspace channel picker properties: archived: type: boolean description: Whether Slack reports the channel as archived channelName: type: string description: Current Slack channel name consentState: type: string description: "Existing Hephaestus monitoring state, if already allow-listed" enum: - PENDING - ACTIVE - PAUSED - REVOKED member: type: boolean description: Whether the app bot is already a member privateChannel: type: boolean description: Whether this is a private channel slackChannelId: type: string description: Stable Slack channel id required: - channelName - slackChannelId SlackChannelConsentEvent: type: object description: An immutable Slack channel consent-transition audit entry properties: actorUserId: type: integer format: int64 description: Workspace user id of the admin who made the change createdAt: type: string format: date-time description: When the transition was recorded fromState: type: string description: State the channel left (absent for the very first record) enum: - PENDING - ACTIVE - PAUSED - REVOKED id: type: integer format: int64 description: Audit entry id reason: type: string description: Optional free-text reason the admin supplied slackChannelId: type: string description: Slack channel id the transition applied to toState: type: string description: State the channel entered enum: - PENDING - ACTIVE - PAUSED - REVOKED required: - createdAt - id - slackChannelId - toState SlackMonitoredChannel: type: object description: An allow-listed Slack channel with its consent state and person opt-out count properties: channelName: type: string description: "Human-readable channel name, if known" consentAnnouncedAt: type: string format: date-time description: When the in-channel consent announcement was posted (stamped on first activation) consentState: type: string description: Current per-channel consent lifecycle state enum: - PENDING - ACTIVE - PAUSED - REVOKED createdAt: type: string format: date-time description: When the channel was first discovered / allow-listed id: type: integer format: int64 description: Internal allow-list row id optedOutMemberCount: type: integer format: int64 description: Number of workspace members who have opted out of ingestion (workspace-wide) slackChannelId: type: string description: Slack channel id (stable C…/G… id; the natural key) slackTeamId: type: string description: Slack team (workspace) id the channel belongs to required: - consentState - createdAt - id - optedOutMemberCount - slackChannelId - slackTeamId SlackUserPreferences: type: object properties: workspaces: type: array items: $ref: "#/components/schemas/SlackUserWorkspacePreferences" required: - workspaces SlackUserWorkspacePreferences: type: object properties: activeMonitoredChannelCount: type: integer format: int64 channelMessagesAllowed: type: boolean slackDisplayName: type: string slackTeamId: type: string slackTeamName: type: string slackUserId: type: string workspaceName: type: string workspaceSlug: type: string required: - slackTeamId - slackUserId - workspaceName - workspaceSlug SlippedPractice: type: object description: A practice a run recorded a problem about for this developer properties: practiceName: type: string practiceSlug: type: string required: - practiceName - practiceSlug Sort: type: object properties: empty: type: boolean sorted: type: boolean unsorted: type: boolean SubmitSurvey: type: object properties: answers: type: array items: $ref: "#/components/schemas/Answer" maxItems: 20 minItems: 0 required: - answers Survey: type: object properties: active: type: boolean createdAt: type: string format: date-time createdBy: $ref: "#/components/schemas/FeedbackAccountRef" description: type: string endsAt: type: string format: date-time id: type: string format: uuid participation: $ref: "#/components/schemas/ParticipationCounts" purpose: type: string enum: - PRODUCT - RESEARCH questions: type: array items: $ref: "#/components/schemas/Question" researchOrganization: type: string description: the organisation a research survey was published for; absent for a product survey startsAt: type: string format: date-time title: type: string workspace: $ref: "#/components/schemas/FeedbackWorkspaceRef" required: - active - createdAt - description - id - participation - purpose - questions - startsAt - title SurveyEdit: type: object properties: active: type: boolean description: type: string maxLength: 500 minLength: 0 endsAt: type: string format: date-time startsAt: type: string format: date-time title: type: string maxLength: 160 minLength: 0 required: - active - description - startsAt - title SurveyEmailInvitationRequest: type: object properties: sendReminder: type: boolean SurveyEmailInvitationSummary: type: object description: "Counts refer to email requests, not in-app invitations or responses.\ \ Accepted means SMTP relay acceptance." properties: accepted: type: integer format: int32 alreadyRequested: type: integer format: int32 deliveryConfigured: type: boolean eligible: type: integer format: int32 queued: type: integer format: int32 remaining: type: integer format: int32 required: - accepted - alreadyRequested - deliveryConfigured - eligible - queued - remaining SurveyInvitation: type: object properties: description: type: string endsAt: type: string format: date-time id: type: string format: uuid purpose: type: string enum: - PRODUCT - RESEARCH questions: type: array items: $ref: "#/components/schemas/Question" researchOrganization: type: string description: "set for a research survey: the organisation whose study the\ \ answers join" seen: type: boolean description: the account has been shown this invitation; the webapp nudges only while false title: type: string required: - description - id - purpose - questions - seen - title SurveyResponse: type: object properties: account: $ref: "#/components/schemas/FeedbackAccountRef" answers: type: array items: $ref: "#/components/schemas/Answer" decidedAt: type: string format: date-time id: type: string format: uuid status: type: string enum: - INVITED - RESPONDED - DECLINED workspace: $ref: "#/components/schemas/FeedbackWorkspaceRef" required: - decidedAt - id - status SurveySummary: type: object properties: participation: $ref: "#/components/schemas/ParticipationCounts" questions: type: array items: $ref: "#/components/schemas/QuestionSummary" required: - participation - questions SyncJob: type: object description: One sync_job row — a single INITIAL/RECONCILIATION/BACKFILL pass for a connection properties: cancelRequested: type: boolean description: Whether a cooperative cancel was requested createdAt: type: string format: date-time description: When the job row was created errorSummary: type: string description: "Truncated error summary, set on FAILED" finishedAt: type: string format: date-time description: When the job finished (any terminal status) id: type: integer format: int64 description: Job id itemsProcessed: type: integer format: int32 description: "Coarse progress: items processed so far" itemsTotal: type: integer format: int32 description: "Coarse progress: total items, if known" progress: type: object additionalProperties: {} description: "Per-phase progress detail, integration-specific shape" startedAt: type: string format: date-time description: When the job started running status: type: string description: Job status enum: - PENDING - RUNNING - SUCCEEDED - SUCCEEDED_WITH_WARNINGS - FAILED - CANCELLED trigger: type: string description: What initiated this job enum: - SCHEDULED - MANUAL - LIFECYCLE - SYSTEM triggeredByUserId: type: integer format: int64 description: "Account id of the admin who triggered this job, if MANUAL" type: type: string description: What kind of pass this is enum: - INITIAL - RECONCILIATION - BACKFILL required: - cancelRequested - createdAt - id - status - trigger - type SyncResourceCount: type: object description: "One entity class mirrored within a resource (issues, pull requests,\ \ comments, messages, …)" properties: count: type: integer format: int64 description: Mirrored row count for this class key: type: string description: Stable machine token for this class enum: - issues - pullRequests - issueComments - reviews - reviewComments - commits - messages - documents example: pullRequests label: type: string description: Display name example: Pull requests lastSyncedAt: type: string format: date-time description: When this class was last synced. Null means the integration does not track a per-class watermark — not that the class has never synced. required: - count - key - label SyncResourceState: type: object description: One synced resource (repository / channel / collection) — unified read-model row properties: backfillCompletedThrough: type: string format: date-time description: Per-resource backfill horizon backfillPercent: type: integer format: int32 description: Per-resource backfill percent counts: type: array description: "Per-entity-class breakdown behind itemCount. One entry per\ \ class the integration actually mirrors — 6 for an SCM repository, 1\ \ for a Slack channel or Outline collection. Never null; empty when the\ \ resource has never synced." items: $ref: "#/components/schemas/SyncResourceCount" externalId: type: string description: Vendor-side identifier id: type: integer format: int64 description: The integration's own row id itemCount: type: integer format: int64 description: Headline mirrored item count — the rollup of `counts` lastError: type: string description: "Last sync error, if any" lastSyncedAt: type: string format: date-time description: Last successful sync timestamp across all entity classes name: type: string description: Display name state: type: string description: Integration-defined status string type: type: string description: Resource kind enum: - REPOSITORY - CHANNEL - COLLECTION upstreamCount: type: integer format: int64 description: "Vendor-reported upstream count, if cheaply available" required: - counts - externalId - id - name - state - type TeamInfo: type: object description: "Detailed information about a team including members, repositories,\ \ and labels" properties: description: type: string description: Description of the team hidden: type: boolean description: Whether the team is hidden from workspace activity htmlUrl: type: string description: URL to the team's page on the git provider id: type: integer format: int64 description: Unique identifier of the team labels: type: array description: Labels configured as filters for this team items: $ref: "#/components/schemas/LabelInfo" members: type: array description: Members of the team (excluding bots) items: $ref: "#/components/schemas/UserInfo" membershipCount: type: integer format: int32 description: Total count of team memberships name: type: string description: Name of the team organization: type: string description: Organization the team belongs to parentId: type: integer format: int64 description: "ID of the parent team, if this is a sub-team" privacy: type: string description: Privacy level of the team (SECRET or VISIBLE) enum: - SECRET - VISIBLE repoPermissionCount: type: integer format: int32 description: Count of repository permissions repositories: type: array description: Repositories the team has access to items: $ref: "#/components/schemas/RepositoryInfo" slug: type: string description: Stable team key for URL filters required: - hidden - id - labels - members - membershipCount - name - repoPermissionCount - repositories - slug TeamRef: type: object description: "A team, by name" properties: id: type: integer format: int64 description: Identifier of the team name: type: string description: Name of the team example: Platform required: - id - name TeamSummary: type: object description: Lightweight summary of a team without member/repository details properties: description: type: string description: Description of the team hidden: type: boolean description: Whether the team is hidden from workspace activity htmlUrl: type: string description: URL to the team's page on the git provider id: type: integer format: int64 description: Unique identifier of the team name: type: string description: Name of the team organization: type: string description: Organization the team belongs to parentId: type: integer format: int64 description: "ID of the parent team, if this is a sub-team" privacy: type: string description: Privacy level of the team (SECRET or VISIBLE) enum: - SECRET - VISIBLE required: - hidden - id - name TimeBucketSize: type: string description: "How long each bucket of a range is: a day for ranges up to 31\ \ days, a week from Monday for ranges up to 184 days, a month for longer ones" enum: - DAY - WEEK - MONTH TracedArtifact: type: object description: "An artifact this workspace recorded something about, and how much\ \ of it turned into review" properties: artifactId: type: integer format: int64 artifactKind: type: string lastSignalAt: type: string format: date-time reviewedSignalCount: type: integer format: int32 description: How many of them started a review reviewedWork: $ref: "#/components/schemas/ReviewedWorkRef" description: "The work as every surface names it: its provider, the label\ \ the provider writes (\"#1423\", \"!1423\"), its title, where it sits\ \ and where to open it; the link is absent for deleted work" signalCount: type: integer format: int32 description: Occurrences recorded on this artifact required: - artifactId - artifactKind - lastSignalAt - reviewedSignalCount - reviewedWork - signalCount TracedSignal: type: object description: "One thing that happened to this artifact, and what the system\ \ did about it" properties: discoveredVia: type: string description: "How we came to know: by event, by sync, by hand, or by backfill" enum: - EVENT - SYNC - MANUAL - BACKFILL - SWEEP displayName: type: string description: "What to print for the signal, from the artifact kind's descriptor" id: type: string format: uuid description: This occurrence's own identity; what a practice's occasionedById points at occurredAt: type: string format: date-time description: "When it happened upstream; for a sync discovery, only as precise\ \ as the sync" reviewId: type: string format: uuid description: "The review this occurrence started, when it started one" revision: type: string description: Which version of the artifact this occurrence is about; the reason editing a description can be re-measured while the commits stay put signal: type: string description: "Signal name, for matching and linking; never printed" state: type: string enum: - RECORDED - DEFERRED - TRIGGERED - SUPPRESSED - PENDING - LAPSED stateReason: type: string description: Why it ended in that state; null once it triggered a review enum: - GATE_SKIPPED - COOLDOWN_ACTIVE - REQUEST_COOLDOWN_ACTIVE - REQUESTER_QUOTA_EXHAUSTED - CONCURRENT_DUPLICATE - COALESCED - OUT_OF_REVIEW_SCOPE - BOT_AUTHOR - BOT_REVIEWER - STALE_ROLLOUT_REVISION - WORKSPACE_INACTIVE - PRACTICES_DISABLED - NO_ACTIVE_PRACTICE - REVIEW_MODEL_UNBOUND - MEMBER_AI_DECLINED - PERSON_DATA_ERASED - PRACTICE_AUTONOMY_OFF - BUDGET_EXHAUSTED - SUBJECT_UNLINKED - MERGE_ACTOR_UNAVAILABLE - MODEL_UNAVAILABLE - ARTIFACT_NOT_VISIBLE - PENDING_DEADLINE_EXCEEDED - ARTIFACT_GONE stateReasonDescription: type: string description: "That reason as one sentence for a reader. Render it verbatim:\ \ it is written next to the reason it explains, so every surface that\ \ explains a silence says the same thing" required: - discoveredVia - displayName - id - occurredAt - revision - signal - state TrendOpportunity: type: object properties: bundle: type: string enum: - PREVIOUS - CURRENT - OLDER index: type: integer format: int32 occurredAt: type: string format: date-time outcomes: $ref: "#/components/schemas/OutcomeVector" reviewedWorkId: type: integer format: int64 workKind: type: string required: - bundle - index - occurredAt - outcomes - reviewedWorkId - workKind TrendSupport: type: object properties: bundleSize: type: integer format: int32 calendarSpanDays: type: integer format: int32 comparablePractices: type: integer format: int32 credibilityThreshold: type: number format: double currentOpportunities: type: integer format: int32 eligiblePractices: type: integer format: int32 firstOpportunityAt: type: string format: date-time lastOpportunityAt: type: string format: date-time opportunities: type: integer format: int32 description: "Distinct pieces of reviewed work the trend rests on, across\ \ both bundles" opportunitiesUntilComparable: type: integer format: int32 previousOpportunities: type: integer format: int32 ropeHalfWidth: type: number format: double required: - bundleSize - credibilityThreshold - currentOpportunities - opportunities - opportunitiesUntilComparable - previousOpportunities - ropeHalfWidth TriggerSyncJobRequest: type: object description: Manual sync trigger request body properties: type: type: string description: "RECONCILIATION for a full re-sync, BACKFILL for historical\ \ data" enum: - INITIAL - RECONCILIATION - BACKFILL required: - type UpdateAccountRequest: type: object properties: appRole: type: string UpdateConnectionStatusRequest: type: object description: Request to update a connection's lifecycle status properties: reason: type: string description: Optional human-readable reason recorded on the audit trail state: type: string description: "Target lifecycle state. Admin-settable: ACTIVE, SUSPENDED,\ \ UNINSTALLED." enum: - PENDING - ACTIVE - SUSPENDED - UNINSTALLED required: - state UpdateCuratedStatusRequest: type: object description: Whether new workspaces receive this catalog entry properties: status: type: string enum: - AVAILABLE - RETIRED required: - status UpdateFeedbackWithdrawalRequest: type: object description: "Withdraw a card from a developer's practice page, or restore it" properties: reason: type: string description: "Why, kept with the withdrawal for the workspace's administrators" maxLength: 500 minLength: 0 withdrawn: type: boolean description: true withdraws the card; false restores it required: - reason - withdrawn UpdateInstanceLlmSettingsRequest: type: object description: Update instance-wide LLM governance settings (all fields optional) properties: allowWorkspaceConnections: type: boolean description: Whether workspaces may register their own LLM connections allowedEgressHosts: type: string description: Comma/newline-delimited egress host allowlist; blank clears it UpdateLlmBudgetRequest: type: object description: Set or clear a monthly LLM budget cap properties: monthlyBudgetUsd: type: number format: decimal description: "Cap in USD; 0 pauses the affected work immediately, null removes\ \ the cap. The purse it governs is the one the path names, and only that\ \ one: /admin/workspaces/{workspaceSlug}/llm/budget caps spend on shared\ \ (instance) models, /workspaces/{workspaceSlug}/llm/budget caps the workspace's\ \ spend on its own connected provider. The two are never added together." minimum: 0.00 UpdateLlmConnectionRequest: type: object description: Update an instance LLM provider connection (all fields optional) properties: apiKey: type: string description: New API key (write-only; never returned) clearApiKey: type: boolean description: Set true to clear the stored API key clearConnectionPlatform: type: boolean description: Set true to clear the declared connection platform connectionPlatform: type: string description: Admin-declared connection platform enum: - LOGOS - VLLM - OLLAMA - AZURE - AWS_BEDROCK - GOOGLE_VERTEX - OPENAI - GOOGLE_AI_STUDIO - ALIBABA_CLOUD - GROQ - FIREWORKS - TOGETHER_AI - DEEPINFRA - NEBIUS - OPENROUTER - CLOUDFLARE_AI_GATEWAY - VERCEL_AI_GATEWAY displayName: type: string description: Human-readable name maxLength: 128 minLength: 0 enabled: type: boolean description: Whether the connection is enabled UpdateLlmModelPriceRequest: type: object description: Reprice a model; supersedes the current price properties: note: type: string description: "Note; required when the model is free (e.g. self-hosted, no\ \ cost)" maxLength: 500 minLength: 0 per1mCacheReadUsd: type: number format: decimal description: "Cache-read rate per 1M tokens (USD), if applicable" per1mCacheWriteUsd: type: number format: decimal description: "Cache-write rate per 1M tokens (USD), if applicable" per1mInputUsd: type: number format: decimal description: Input rate per 1M tokens (USD); required when the model has a price per1mOutputUsd: type: number format: decimal description: Output rate per 1M tokens (USD); required when the model has a price pricingMode: type: string description: PRICED shows the price itself; NO_CHARGE is a deliberate no-cost declaration; UNPRICED shows "No price set" enum: - PRICED - NO_CHARGE - UNPRICED required: - pricingMode UpdateLlmModelRequest: type: object description: Update a model's metadata (all fields optional; pricing and sharing are separate) properties: brand: type: string description: Model brand declared by an admin; null keeps current enum: - OPENAI - ANTHROPIC - GEMINI - GEMMA - META - MISTRAL - QWEN - DEEPSEEK - XAI - COHERE - Z_AI - MOONSHOT clearBrand: type: boolean description: Clear the declared model brand clearReasoningEffort: type: boolean description: "True clears the reasoning effort, so the provider's own default\ \ applies" contextWindow: type: integer format: int32 description: Context window in tokens minimum: 1 dataHandlingNote: type: string description: "Admin-only note: region, agreement, renewal date" maxLength: 200 minLength: 0 displayName: type: string description: Human-readable name maxLength: 128 minLength: 0 enabled: type: boolean description: Active toggle (off = existing settings stop working) maxOutputTokens: type: integer format: int32 description: Maximum output tokens minimum: 1 operatedBy: type: string description: Who operates the systems the work is sent to; omit to leave the model undeclared enum: - OWN_ORGANISATION - PROVIDER reasoningEffort: type: string description: Reasoning effort to request; null keeps the current one (see clearReasoningEffort) enum: - NONE - MINIMAL - LOW - MEDIUM - HIGH - XHIGH - MAX UpdateLlmModelSharingRequest: type: object description: "Share with: all workspaces, or a selected set" properties: visibility: type: string description: Share with all workspaces (PUBLIC) or only the selected ones (GRANTED) enum: - PUBLIC - GRANTED workspaceIds: type: array description: Workspace ids to share with when visibility is GRANTED; empty or omitted stages the model without workspace access items: type: integer format: int64 required: - visibility UpdateLoginProviderRequest: type: object properties: baseUrl: type: string clientId: type: string clientSecret: type: string description: Omit to leave the existing secret unchanged displayName: type: string enabled: type: boolean scopes: type: string UpdateNotificationPreferences: type: object properties: productFeedback: type: boolean productSurveys: type: boolean researchSurveys: type: boolean surveySummaries: type: boolean workspaceAlerts: type: boolean required: - productFeedback - productSurveys - researchSurveys - surveySummaries - workspaceAlerts UpdateObservationValidityRequest: type: object description: "Invalidate an observation that was wrong when recorded, or restore\ \ it" properties: reason: type: string description: "Why, kept with the correction; an invalidation reason is shown\ \ to the developer" maxLength: 500 minLength: 0 valid: type: boolean description: false invalidates the observation; true restores it required: - reason - valid UpdateOutlineCollectionStateRequest: type: object description: Transition a mirrored Outline collection to a target mirror state (pause / resume) properties: state: type: string description: Target mirror state enum: - ENABLED - PAUSED required: - state UpdatePracticeAutonomyRequest: type: object description: "Set how much autonomy the system has here, or clear it back to\ \ inherit" properties: autonomy: type: string description: Local autonomy override. Null inherits from the group or workspace. enum: - "OFF" - HUMAN_APPROVAL - AUTOMATIC UpdatePracticeGroupRequest: type: object description: Request to update an existing practice group (PATCH — only non-null fields applied) properties: color: type: string description: Optional palette colour key for the group's chip maxLength: 32 minLength: 0 pattern: "^[a-z]+$" description: type: string description: What this group develops maxLength: 5000 minLength: 0 displayOrder: type: integer format: int32 description: Sort order within the workspace minimum: 0 icon: type: string description: Optional lucide icon name giving the group a glanceable identity maxLength: 64 minLength: 0 pattern: "^[A-Za-z0-9]+$" name: type: string description: Human-readable name maxLength: 128 minLength: 3 pattern: .*\S.* visibleInPracticeDashboards: type: boolean description: Whether this group is shown in practice dashboards UpdatePracticeRequest: type: object additionalProperties: false description: Request to update a practice; omitted fields remain unchanged properties: automatedReviewPolicy: $ref: "#/components/schemas/PracticeAutomatedReviewPolicy" description: "Replacement review settings; omit to preserve them, or to\ \ take the recommended ones when the signals move the practice to a different\ \ kind of work" clear: type: array description: Optional fields to clear before applying supplied values items: type: string enum: - PRECONDITION - PRECOMPUTE_SCRIPT - WHY_IT_MATTERS - WHAT_GOOD_LOOKS_LIKE uniqueItems: true criteria: type: string description: Practice review criteria maxLength: 50000 minLength: 0 pattern: "[\\s\\S]*\\S[\\s\\S]*" definitionChanges: type: array description: Explicit intent to change the gate or the person judged items: type: string enum: - PRECONDITION - SUBJECT uniqueItems: true deliveryBehavior: $ref: "#/components/schemas/PracticeDeliveryBehavior" evidenceRequirements: type: array items: $ref: "#/components/schemas/PracticeEvidenceRequirement" group: $ref: "#/components/schemas/BindPracticeGroupRequest" description: Catalog placement to apply with the definition update; omit to leave unchanged name: type: string description: Human-readable name example: PR Description Quality maxLength: 128 minLength: 3 pattern: .*\S.* precomputeScript: type: string description: TypeScript/Node static analysis run before automated review maxLength: 100000 minLength: 0 precondition: $ref: "#/components/schemas/PracticePrecondition" reviewWhen: type: object additionalProperties: type: array items: type: string uniqueItems: true description: Automatic review state selections. An empty object imposes no state restrictions. Each selected dimension requires a nonempty set of non-null values offered by the work type descriptor. Values within a dimension are alternatives; all selected dimensions must match. signals: type: array items: type: string maxItems: 2147483647 minItems: 1 subject: type: string enum: - AUTHOR - ASSIGNEE - REVIEWER - MERGER whatGoodLooksLike: type: string description: Concrete example shown to the developer; not review criteria maxLength: 2000 minLength: 0 pattern: "[\\s\\S]*\\S[\\s\\S]*" whyItMatters: type: string description: Plain-language rationale shown to the developer maxLength: 2000 minLength: 0 pattern: "[\\s\\S]*\\S[\\s\\S]*" UpdatePracticeReviewSettingsRequest: type: object description: Update per-workspace practice-review policy. Null fields unchanged; 'reset' clears to inherit. properties: cooldownMinutes: type: integer format: int32 description: Minimum minutes between reviews for the same PR; 0 disables the cooldown maximum: 1440 minimum: 0 defaultAutonomy: type: string description: How much autonomy the system has over practices and groups that hold no autonomy of their own. The one decision that moves a whole workspace at once. Null leaves it unchanged; name DEFAULT_AUTONOMY in 'reset' to clear it. enum: - "OFF" - HUMAN_APPROVAL - AUTOMATIC deliverToMerged: type: boolean description: Deliver feedback to already-merged PRs/MRs deliveryStatus: type: string description: Pause or activate external feedback. Resume never releases work from an older revision. enum: - ACTIVE - PAUSED generatedPaths: type: object additionalProperties: type: array items: type: string description: Patch generated-path patterns per monitored repository. An empty list clears that repository. Null leaves all unchanged. reset: type: array description: Fields to reset back to inherit items: type: string enum: - SKIP_DRAFTS - DELIVER_TO_MERGED - COOLDOWN_MINUTES - REVIEW_SCOPE - DEFAULT_AUTONOMY uniqueItems: true reviewScope: $ref: "#/components/schemas/WorkspaceReviewScope" description: Replaces repository and person coverage wholesale. Null leaves it unchanged. UpdateRepositorySettingsRequest: type: object description: Request to update repository contribution visibility settings in a workspace properties: hiddenFromContributions: type: boolean description: Whether activity in this repository should be left out of the team's activity required: - hiddenFromContributions UpdateReviewBackfillRunStatusRequest: type: object description: |- The lifecycle transitions an admin can ask for.

RUNNING is the confirmation: it is the point at which somebody accepts the estimate they were shown and authorises the spend. CANCELLED stops a campaign for good. Every other transition — pausing on an exhausted budget, resuming when it clears, completing at the end of the scope — belongs to the driver, and is refused here so the state on screen always reflects something the system decided or something a person did, never a mixture. properties: status: type: string description: RUNNING confirms the estimate and starts the campaign; CANCELLED stops it for good enum: - RUNNING - CANCELLED required: - status UpdateReviewSweepScheduleRequest: type: object description: |- Replace a sweep schedule's terms.

Every field is required: a schedule is three numbers that only mean anything together — a cadence changed without its lookback can silently make a window illegal, or leave days nothing ever sweeps. The artifact kind is not among them; a schedule for a different kind of work is a different schedule. properties: cadence: type: string description: How often the sweep runs enum: - DAILY - WEEKLY enabled: type: boolean description: Whether the scheduler acts on this row; a disabled schedule keeps its terms lookbackDays: type: integer format: int32 description: "How far back each sweep looks, in days" example: 2 maximum: 7 minimum: 1 required: - cadence - enabled - lookbackDays UpdateSilentModeRequest: type: object properties: engaged: type: boolean reason: type: string maxLength: 500 minLength: 0 required: - engaged UpdateSlackChannelConsentRequest: type: object description: Transition a Slack channel to a target consent state properties: consentState: type: string description: Target consent state enum: - PENDING - ACTIVE - PAUSED - REVOKED reason: type: string description: Optional free-text reason recorded in the immutable audit trail maxLength: 2000 minLength: 0 required: - consentState UpdateSlackUserPreferencesRequest: type: object properties: channelMessagesAllowed: type: boolean required: - channelMessagesAllowed UpdateSyncJobRequest: type: object properties: cancelRequested: type: boolean required: - cancelRequested UpdateTeamSettingsRequest: type: object description: Request to update team visibility settings in a workspace properties: hidden: type: boolean description: Whether the team should be hidden from workspace activity required: - hidden UpdateWorkspaceFeaturesRequest: type: object description: Request to turn practice reviews and their triggers on or off. Null fields are left unchanged. properties: practiceReviewAutoTriggerEnabled: type: boolean description: Enable automatic practice reviews triggered by PR events practiceReviewManualTriggerEnabled: type: boolean description: Enable manual practice reviews triggered through a bot command practicesEnabled: type: boolean description: Enable the practice review feature UpdateWorkspaceLlmConnectionRequest: type: object description: Update your AI provider connection (all fields optional) properties: apiKey: type: string description: New API key (write-only; never returned) clearApiKey: type: boolean description: Set true to clear the stored API key clearConnectionPlatform: type: boolean description: Set true to clear the declared connection platform connectionPlatform: type: string description: Admin-declared connection platform enum: - LOGOS - VLLM - OLLAMA - AZURE - AWS_BEDROCK - GOOGLE_VERTEX - OPENAI - GOOGLE_AI_STUDIO - ALIBABA_CLOUD - GROQ - FIREWORKS - TOGETHER_AI - DEEPINFRA - NEBIUS - OPENROUTER - CLOUDFLARE_AI_GATEWAY - VERCEL_AI_GATEWAY displayName: type: string description: Human-readable name maxLength: 128 minLength: 0 enabled: type: boolean description: Whether the connection is active UpdateWorkspaceLlmModelRequest: type: object description: Update a model on your AI provider (all fields optional) properties: brand: type: string description: Model brand declared by an admin; null keeps current enum: - OPENAI - ANTHROPIC - GEMINI - GEMMA - META - MISTRAL - QWEN - DEEPSEEK - XAI - COHERE - Z_AI - MOONSHOT clearBrand: type: boolean description: Clear the declared model brand clearReasoningEffort: type: boolean description: "True clears the reasoning effort, so the provider's own default\ \ applies" contextWindow: type: integer format: int32 description: Context window in tokens minimum: 1 dataHandlingNote: type: string description: "Admin-only note: region, agreement, renewal date" maxLength: 200 minLength: 0 displayName: type: string description: Human-readable name maxLength: 128 minLength: 0 enabled: type: boolean description: Active toggle maxOutputTokens: type: integer format: int32 description: Maximum output tokens minimum: 1 operatedBy: type: string description: Who operates the systems the work is sent to; omit to leave the model undeclared enum: - OWN_ORGANISATION - PROVIDER per1mCacheReadUsd: type: number format: decimal description: "Cache-read rate per 1M tokens (USD), if applicable" per1mCacheWriteUsd: type: number format: decimal description: "Cache-write rate per 1M tokens (USD), if applicable" per1mInputUsd: type: number format: decimal description: Input rate per 1M tokens (USD) per1mOutputUsd: type: number format: decimal description: Output rate per 1M tokens (USD) priceNote: type: string description: "Note; required when the model is free (e.g. self-hosted, no\ \ cost)" maxLength: 500 minLength: 0 pricingMode: type: string description: "Pricing mode; when given, replaces the price wholesale (see\ \ class docs)" enum: - PRICED - NO_CHARGE - UNPRICED reasoningEffort: type: string description: Reasoning effort to request; null keeps the current one (see clearReasoningEffort) enum: - NONE - MINIMAL - LOW - MEDIUM - HIGH - XHIGH - MAX UpdateWorkspacePublicActivityRequest: type: object properties: allowSearchEngines: type: boolean publicActivityEnabled: type: boolean required: - allowSearchEngines - publicActivityEnabled UpdateWorkspaceStatusRequest: type: object description: Request to update the workspace lifecycle status properties: status: type: string description: "Target lifecycle status. PURGED is not a status transition:\ \ purge is irreversible and owner-only, so it lives at DELETE /workspaces/{workspaceSlug}." enum: - ACTIVE - SUSPENDED required: - status UpdateWorkspaceTokenRequest: type: object description: Request to update the workspace's SCM Personal Access Token properties: personalAccessToken: type: string description: SCM Personal Access Token for API access minLength: 1 required: - personalAccessToken UserInfo: type: object description: Information about a user from the git provider properties: avatarUrl: type: string description: URL to the user's avatar image email: type: string description: "Email address of the user, if public" htmlUrl: type: string description: URL to the user's profile on the git provider id: type: integer format: int64 description: Unique identifier of the user login: type: string description: Login/username of the user name: type: string description: Display name of the user required: - avatarUrl - htmlUrl - id - login - name UserSettings: type: object description: User preferences and settings properties: practiceFeedbackDeliveryEnabled: type: boolean description: "Whether new practice-feedback comments may be delivered on\ \ issues, pull requests, and merge requests authored by the user, together\ \ with related Slack reminders" required: - practiceFeedbackDeliveryEnabled UserTeams: type: object properties: email: type: string hidden: type: boolean id: type: integer format: int64 login: type: string name: type: string teams: type: array items: $ref: "#/components/schemas/TeamSummary" uniqueItems: true url: type: string required: - id - login - name - teams - url UserViewUser: type: object properties: accountId: type: integer format: int64 accountStatus: type: string login: type: string name: type: string userId: type: integer format: int64 required: - login - userId WorkItem: type: object description: A pull request or issue properties: author: $ref: "#/components/schemas/UserInfo" description: The author checks: type: string description: "What the checks said about the pull request's current head,\ \ when known" enum: - SUCCESS - FAILURE - PENDING - CANCELLED - NONE - NO_PIPELINE - SKIPPED createdAt: type: string format: date-time description: When it was created htmlUrl: type: string description: Link to the pull request or issue on the provider id: type: integer format: int64 description: Identifier of the pull request or issue isDraft: type: boolean description: Whether the pull request is a draft; false for issues number: type: integer format: int32 description: Number within the repository example: 42 repository: $ref: "#/components/schemas/RepositoryInfo" description: The repository requestedTeams: type: array description: The member's teams the pull request asks for a review; only team review requests list them items: $ref: "#/components/schemas/TeamRef" reviewDecision: type: string description: "The pull request's review decision, when the provider reported\ \ one" enum: - APPROVED - CHANGES_REQUESTED - REVIEW_REQUIRED reviewers: type: array description: "The pull request's reviewers besides its author, where each\ \ review stands; only open work lists them" items: $ref: "#/components/schemas/Reviewer" state: type: string description: Current state enum: - OPEN - CLOSED - MERGED title: type: string description: Title type: type: string description: Whether this is a pull request or an issue enum: - PULL_REQUEST - ISSUE updatedAt: type: string format: date-time description: When it was last updated required: - id - isDraft - number - state - title - type WorkItemList: type: object description: "Pull requests or issues, most recently updated first, up to a\ \ limit" properties: content: type: array description: "The work, most recently updated first" items: $ref: "#/components/schemas/WorkItem" hasMore: type: boolean description: Whether more work exists than the list holds required: - content - hasMore Workspace: type: object description: Complete workspace information including configuration and settings properties: accountLogin: type: string description: Git provider account login associated with this workspace createdAt: type: string format: date-time description: Timestamp when the workspace was created displayName: type: string description: Human-readable name of the workspace gitlabWebhookRegistered: type: boolean description: Whether a GitLab webhook has been auto-registered for this workspace hasPersonalAccessToken: type: boolean description: Whether a Personal Access Token is configured hasSlackToken: type: boolean description: Whether Slack token is configured id: type: integer format: int64 description: Unique identifier of the workspace installationId: type: integer format: int64 description: "GitHub App installation ID, if linked" installationLinkedAt: type: string format: date-time description: Timestamp when the GitHub App installation was linked kind: type: string description: Integration kind backing this workspace (GITHUB or GITLAB) practiceReviewAutoTriggerEnabled: type: boolean description: Whether automatic practice reviews triggered by PR events are enabled practiceReviewManualTriggerEnabled: type: boolean description: Whether manual practice reviews triggered through a bot command are enabled practicesEnabled: type: boolean description: Whether practice reviews are on providerType: type: string description: High-level git provider type for the workspace's SCM connection (null if none bound) enum: - GITHUB - GITLAB - SLACK - OUTLINE publicActivityEnabled: type: boolean description: Whether this workspace has enabled its public activity page serverUrl: type: string description: Custom server URL for self-hosted instances (null for cloud defaults) slackConnectionId: type: integer format: int64 description: "ID of the active Slack connection, if any — addresses PATCH\ \ /connections/{id}/status" status: type: string description: "Current lifecycle status of the workspace (PENDING, ACTIVE,\ \ ARCHIVED)" updatedAt: type: string format: date-time description: Timestamp when the workspace was last updated workspaceAddress: type: string description: Canonical workspace address. Uses the apex path when subdomains are off. workspaceSlug: type: string description: URL-friendly identifier for the workspace example: my-workspace required: - accountLogin - createdAt - displayName - gitlabWebhookRegistered - hasPersonalAccessToken - hasSlackToken - id - practiceReviewAutoTriggerEnabled - practiceReviewManualTriggerEnabled - practicesEnabled - publicActivityEnabled - status - updatedAt - workspaceAddress - workspaceSlug WorkspaceAiModel: type: object description: A model this answer would use here. properties: brand: type: string enum: - OPENAI - ANTHROPIC - GEMINI - GEMMA - META - MISTRAL - QWEN - DEEPSEEK - XAI - COHERE - Z_AI - MOONSHOT connectionPlatform: type: string enum: - LOGOS - VLLM - OLLAMA - AZURE - AWS_BEDROCK - GOOGLE_VERTEX - OPENAI - GOOGLE_AI_STUDIO - ALIBABA_CLOUD - GROQ - FIREWORKS - TOGETHER_AI - DEEPINFRA - NEBIUS - OPENROUTER - CLOUDFLARE_AI_GATEWAY - VERCEL_AI_GATEWAY dataHandlingTier: type: string enum: - IN_HOUSE - CLOUD - UNDECLARED name: type: string required: - dataHandlingTier - name WorkspaceAiOption: type: object properties: choice: type: string enum: - NO_AI - IN_HOUSE_ONLY - CLOUD mentorReady: type: boolean models: type: array items: $ref: "#/components/schemas/WorkspaceAiModel" practiceReviewsReady: type: boolean required: - choice - mentorReady - models - practiceReviewsReady WorkspaceGroupSplit: type: object description: "One practice group: how the developers with a standing split across\ \ it, and where the reader is" properties: groupColor: type: string description: Group colour name groupIcon: type: string description: Group icon name groupName: type: string description: Group name groupSlug: type: string description: Group slug practices: type: array description: "The group's practices review is admitted for, the same for\ \ every reader, each split on its own, in catalog order" items: $ref: "#/components/schemas/WorkspacePracticeSplit" split: $ref: "#/components/schemas/WorkspaceSplit" description: How the developers with a standing split across the group yourStanding: type: string description: "The reader's current standing in the group, the one their\ \ practice profile shows: the part they are marked in. Absent unless the\ \ split counts the reader" enum: - DEVELOPING - STRENGTH - MIXED - NOT_OBSERVED - NO_OPPORTUNITY required: - groupName - groupSlug - practices - split WorkspaceListItem: type: object description: Summary information about a workspace for list views properties: accountLogin: type: string description: Git provider account login associated with this workspace createdAt: type: string format: date-time description: Timestamp when the workspace was created displayName: type: string description: Human-readable name of the workspace id: type: integer format: int64 description: Unique identifier of the workspace practicesEnabled: type: boolean description: Whether practice reviews are on providerType: type: string description: "High-level git provider type (GITHUB or GITLAB), or null if\ \ no SCM connection bound" enum: - GITHUB - GITLAB - SLACK - OUTLINE publishesPublicActivity: type: boolean description: "Whether the public activity page is live: the instance allows\ \ it and the workspace turned it on" status: type: string description: "Current lifecycle status of the workspace (PENDING, ACTIVE,\ \ ARCHIVED)" workspaceAddress: type: string description: Canonical workspace address. Uses the apex path when subdomains are off. workspaceSlug: type: string description: URL-friendly identifier for the workspace example: my-workspace required: - accountLogin - createdAt - displayName - id - practicesEnabled - publishesPublicActivity - status - workspaceAddress - workspaceSlug WorkspaceLlmConnection: type: object description: Your AI provider connection (API key redacted) properties: apiKeyLast4: type: string description: "Last four characters of the stored API key, if any" apiProtocol: type: string description: Wire protocol example: openai-responses authMode: type: string description: Credential shape enum: - BEARER - API_KEY baseUrl: type: string description: Provider base URL connectionPlatform: type: string description: Admin-declared connection platform enum: - LOGOS - VLLM - OLLAMA - AZURE - AWS_BEDROCK - GOOGLE_VERTEX - OPENAI - GOOGLE_AI_STUDIO - ALIBABA_CLOUD - GROQ - FIREWORKS - TOGETHER_AI - DEEPINFRA - NEBIUS - OPENROUTER - CLOUDFLARE_AI_GATEWAY - VERCEL_AI_GATEWAY createdAt: type: string format: date-time description: Creation timestamp displayName: type: string description: Human-readable name enabled: type: boolean description: Whether the connection is active hasApiKey: type: boolean description: Whether an API key is stored id: type: integer format: int64 description: Connection ID slug: type: string description: Unique slug within the workspace example: openai-prod updatedAt: type: string format: date-time description: Last update timestamp required: - apiProtocol - authMode - baseUrl - createdAt - displayName - enabled - hasApiKey - id - slug WorkspaceLlmModel: type: object description: A model on your AI provider properties: brand: type: string description: Model brand declared by an admin; display only enum: - OPENAI - ANTHROPIC - GEMINI - GEMMA - META - MISTRAL - QWEN - DEEPSEEK - XAI - COHERE - Z_AI - MOONSHOT connectionDisplayName: type: string description: Owning connection's display name connectionId: type: integer format: int64 description: Owning connection id contextWindow: type: integer format: int32 description: Context window in tokens createdAt: type: string format: date-time description: Creation timestamp currency: type: string description: Currency code dataHandlingNote: type: string description: "Admin-only note: region, agreement, renewal date" dataHandlingTier: type: string description: Data-handling tier derived from the operator; UNDECLARED until it is set enum: - IN_HOUSE - CLOUD - UNDECLARED displayName: type: string description: Human-readable name enabled: type: boolean description: Active toggle id: type: integer format: int64 description: Model id maxOutputTokens: type: integer format: int32 description: Maximum output tokens operatedBy: type: string description: Who operates the systems the work is sent to; null until declared enum: - OWN_ORGANISATION - PROVIDER per1mCacheReadUsd: type: number format: decimal description: Cache-read rate per 1M tokens (USD) per1mCacheWriteUsd: type: number format: decimal description: Cache-write rate per 1M tokens (USD) per1mInputUsd: type: number format: decimal description: Input rate per 1M tokens (USD) per1mOutputUsd: type: number format: decimal description: Output rate per 1M tokens (USD) priceNote: type: string description: Price note pricingMode: type: string description: Pricing mode enum: - PRICED - NO_CHARGE - UNPRICED reasoningEffort: type: string description: "Reasoning effort requested of the model; null sends none,\ \ the provider's default applies" enum: - NONE - MINIMAL - LOW - MEDIUM - HIGH - XHIGH - MAX slug: type: string description: Unique slug within the workspace updatedAt: type: string format: date-time description: Last update timestamp upstreamModelId: type: string description: Upstream provider model id required: - connectionDisplayName - connectionId - createdAt - currency - dataHandlingTier - displayName - enabled - id - pricingMode - slug - upstreamModelId WorkspaceLlmProbeResult: type: object description: Result of testing your AI provider connection properties: message: type: string description: Human-readable diagnostic when not reachable modelCount: type: integer format: int32 description: How many models the provider listed (0 if unreachable) reachable: type: boolean description: Whether the provider answered required: - modelCount - reachable WorkspaceLlmSettings: type: object description: The instance LLM policy as it applies to this workspace (read-only) properties: ownProviderAllowed: type: boolean description: Whether this workspace may register its own LLM provider connections required: - ownProviderAllowed WorkspaceLlmUsageReport: type: object description: "One calendar month of a workspace's LLM spend, rolled up from\ \ the usage ledger" properties: byDay: type: array items: $ref: "#/components/schemas/LlmUsageByDay" byJobType: type: array items: $ref: "#/components/schemas/LlmUsageByJobType" fx: $ref: "#/components/schemas/FxRateInfo" description: Display-only conversion when the instance has a display currency. Absent = show USD only. instanceBudgetVerdict: type: string description: "Whether host-funded (shared-model) spend is within its cap,\ \ has reached it, or cannot be confirmed because some shared-model usage\ \ has no price set." enum: - WITHIN - EXHAUSTED - UNVERIFIABLE instanceMonthlyBudgetUsd: type: number format: decimal description: Monthly cap in USD on spend the host pays for (shared models); null = uncapped. Set by instance admins only — a workspace admin can see it but not change it. instancePaused: type: boolean description: "Whether work on SHARED models is currently paused for this\ \ workspace. Authoritative — it mirrors the live gate rather than being\ \ derivable from the verdict alone. Always false for a past month, which\ \ cannot pause anything." instanceTotalCostUsd: type: number format: decimal description: "This month's confirmed spend on shared (instance) models,\ \ in USD — the figure instanceMonthlyBudgetUsd compares against. A floor,\ \ not the full total, while unpricedEventCount is non-zero." month: type: string description: "Calendar month (UTC), ISO yyyy-MM" example: 2026-07 ownProviderBudgetVerdict: type: string description: "The same verdict for spend on this workspace's own provider,\ \ against its own cap." enum: - WITHIN - EXHAUSTED - UNVERIFIABLE ownProviderMonthlyBudgetUsd: type: number format: decimal description: Monthly cap in USD on spend this workspace pays for through its own connected provider; null = uncapped. Set by this workspace's own admins. ownProviderPaused: type: boolean description: Whether work on this workspace's OWN provider is currently paused. ownProviderTotalCostUsd: type: number format: decimal description: "This month's confirmed spend on this workspace's own connected\ \ provider(s), in USD — the figure ownProviderMonthlyBudgetUsd compares\ \ against. Different money from instanceTotalCostUsd: the two are never\ \ added together." unpricedEventCount: type: integer format: int64 description: "Calls this month (either purse) whose price is not yet known.\ \ They are excluded from both totals above, so a non-zero value means\ \ the real spend may be higher than shown." required: - byDay - byJobType - instanceBudgetVerdict - instancePaused - instanceTotalCostUsd - month - ownProviderBudgetVerdict - ownProviderPaused - ownProviderTotalCostUsd - unpricedEventCount WorkspaceMembership: type: object description: A user's membership in a workspace properties: createdAt: type: string format: date-time description: Timestamp when the membership was created eligibleForPracticeReview: type: boolean description: Whether this linked human member can be selected for practice-review coverage hidden: type: boolean description: Whether the member is left out of workspace activity role: type: string description: "Role of the user in this workspace (OWNER, ADMIN, MEMBER)" enum: - OWNER - ADMIN - MEMBER userId: type: integer format: int64 description: Unique identifier of the user userLogin: type: string description: Login/username of the user userName: type: string description: Display name of the user required: - createdAt - eligibleForPracticeReview - hidden - role - userId - userLogin WorkspaceOnboarding: type: object description: |- One member's view of setup in one workspace. aiChoice is the account's answer, the same in every workspace; aiOptions says what this workspace has set up under each answer, which is what differs between workspaces. properties: aiChoice: type: string enum: - NO_AI - IN_HOUSE_ONLY - CLOUD aiChoiceRequired: type: boolean aiOptions: type: array items: $ref: "#/components/schemas/WorkspaceAiOption" enabled: type: boolean links: type: array items: $ref: "#/components/schemas/WorkspaceOnboardingLink" needsSetup: type: boolean workspaceName: type: string required: - aiChoiceRequired - aiOptions - enabled - links - needsSetup - workspaceName WorkspaceOnboardingLink: type: object properties: available: type: boolean connectionId: type: integer format: int64 displayName: type: string linked: type: boolean providerType: type: string registrationId: type: string required: type: boolean teamName: type: string required: - available - connectionId - displayName - linked - providerType - required WorkspaceOnboardingSettings: type: object description: |- aiChoiceRequired is read on GET and ignored on PUT: the server latches it the first time the setup page is enabled and never clears it. properties: aiChoiceRequired: type: boolean enabled: type: boolean requiredConnectionIds: type: array items: type: integer format: int64 exclusiveMinimum: 0 maxItems: 20 minItems: 0 revision: type: integer format: int64 required: - aiChoiceRequired - enabled - requiredConnectionIds - revision WorkspacePracticeSplit: type: object description: "One practice of a group: how the developers with a standing split,\ \ and where the reader is" properties: practiceName: type: string description: Practice name practiceSlug: type: string description: Practice slug split: $ref: "#/components/schemas/WorkspaceSplit" description: How the developers with a standing split across the practice yourStanding: type: string description: "The reader's current standing in the practice, the one their\ \ practice profile shows: the part they are marked in. Absent unless the\ \ split counts the reader" enum: - DEVELOPING - STRENGTH - MIXED - NOT_OBSERVED - NO_OPPORTUNITY required: - practiceName - practiceSlug - split WorkspaceProviders: type: object description: Available workspace creation providers and their configuration properties: creationPolicy: type: string description: Who may create workspaces — ADMIN_ONLY restricts creation to instance admins enum: - ADMIN_ONLY - SELF_SERVICE github: $ref: "#/components/schemas/GitHubProvider" description: "GitHub workspace provider config, null if not available" gitlab: $ref: "#/components/schemas/GitLabProvider" description: "GitLab workspace provider config, null if not available" WorkspaceRange: type: object description: "The middle half of the developers counted: the 25th to the 75th\ \ percentile" properties: high: type: integer format: int32 description: The 75th percentile low: type: integer format: int32 description: The 25th percentile required: - high - low WorkspaceReviewScope: type: object description: An empty repository selection admits no repository work; an empty person selection admits nobody. A selected repository without branches admits all its branches. properties: personMode: type: string enum: - ALL_ELIGIBLE - SELECTED personUserIds: type: array items: type: integer format: int64 repositories: type: array items: $ref: "#/components/schemas/ReviewRepositoryTarget" repositoryMode: type: string enum: - ALL_MONITORED - SELECTED required: - personMode - personUserIds - repositories - repositoryMode WorkspaceSplit: type: object description: "How the developers with a standing split across one practice group\ \ or one practice, counted in developers: a part per verdict, none yet, and\ \ their total" properties: developers: type: integer format: int32 description: "Every developer the split counts, the parts and none yet together,\ \ the reader included when counted" noneYet: type: integer format: int32 description: Developers with a standing in a group shown but none here parts: type: array description: "Developers at each verdict, Needs attention, Mixed feedback\ \ and Going well in that order" items: $ref: "#/components/schemas/WorkspaceSplitPart" required: - developers - noneYet - parts WorkspaceSplitPart: type: object description: The developers at one verdict in a split properties: developers: type: integer format: int32 description: "Developers at the verdict, the reader included when counted" standing: type: string description: The verdict the part counts enum: - DEVELOPING - MIXED - STRENGTH required: - developers - standing WorkspaceTeamRepositorySettings: type: object description: Repository contribution visibility settings for a specific team within a workspace properties: hiddenFromContributions: type: boolean description: Whether activity in this repository is left out of the team's activity repositoryId: type: integer format: int64 description: The repository ID these settings apply to teamId: type: integer format: int64 description: The team ID these settings apply to workspaceId: type: integer format: int64 description: The workspace ID these settings belong to required: - hiddenFromContributions - repositoryId - teamId - workspaceId WorkspaceTeamSettings: type: object description: Team visibility settings for a specific workspace properties: hidden: type: boolean description: Whether the team is hidden from workspace activity teamId: type: integer format: int64 description: The team ID these settings apply to workspaceId: type: integer format: int64 description: The workspace ID these settings belong to required: - hidden - teamId - workspaceId WorkspaceTile: type: object description: "One figure: the reader's own value, then the middle half of the\ \ developers counted" properties: middle: $ref: "#/components/schemas/WorkspaceRange" description: The workspace's middle half; absent while no developer is counted yours: type: integer format: int32 description: The reader's own value required: - yours securitySchemes: bearerAuth: bearerFormat: JWT description: Hephaestus-native JWT bearer authentication. The SPA normally authenticates through the `__Host-HEPHAESTUS_AT` session cookie. This scheme documents the equivalent bearer token. scheme: bearer type: http