/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: What members did and what is open for them
name: Activity
- 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: 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
- 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
- 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
- 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/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/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
/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/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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/Workspace"
description: Workspace returned
security: []
summary: Fetch a workspace by slug
tags:
- workspace
/workspaces/{workspaceSlug}/activity/members:
get:
description: "Members shown in workspace activity, or one team's, ordered by\
\ name."
operationId: listMemberActivity
parameters:
- description: Workspace slug
in: path
name: workspaceSlug
required: true
schema:
type: string
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- description: "A team, with its visible sub-teams; omit for everyone"
in: query
name: teamId
required: false
schema:
type: integer
format: int64
- 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
responses:
"200":
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/MemberActivity"
description: Members listed
"400":
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetail"
description: Invalid range
"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: Team not found
summary: List members with their activity in a time range
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
"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: Member not found
summary: List what is open for a member
tags:
- Activity
/workspaces/{workspaceSlug}/activity/summary:
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. The range is split into days, weeks or months, by its length,\
\ in the given time zone."
operationId: getActivitySummary
parameters:
- description: Workspace slug
in: path
name: workspaceSlug
required: true
schema:
type: string
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- description: The member; omit for everyone
in: query
name: login
required: false
schema:
type: string
- description: "A team, with its visible sub-teams; omit for the workspace"
in: query
name: teamId
required: false
schema:
type: integer
format: int64
- 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/ActivityOverview"
description: Activity counted
"400":
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetail"
description: Invalid range or time zone
"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: Member or team not found
summary: "Count activity in a time range, in total and over time"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- description: The member; omit for everyone
in: query
name: login
required: false
schema:
type: string
- description: "A team, with its visible sub-teams; omit for the workspace"
in: query
name: teamId
required: false
schema:
type: integer
format: int64
- 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: 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: "Invalid range, kind, cursor or size"
"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: Member or team 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
security: []
tags:
- workspace-membership
/workspaces/{workspaceSlug}/members/assign:
post:
operationId: assignRole
parameters:
- description: Workspace slug
in: path
name: workspaceSlug
required: true
schema:
type: string
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/WorkspaceMembership"
description: OK
security: []
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- in: path
name: userId
required: true
schema:
type: integer
format: int64
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/WorkspaceMembership"
description: OK
security: []
tags:
- workspace-membership
/workspaces/{workspaceSlug}/members/{userId}/hidden:
patch:
operationId: updateMemberVisibility
parameters:
- description: Workspace slug
in: path
name: workspaceSlug
required: true
schema:
type: string
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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 holding 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/PracticeProfileOverview"
description: Practice profile overview returned
summary: "What held, 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
- 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
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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/{practiceSlug}:
delete:
operationId: deletePractice
parameters:
- description: Workspace slug
in: path
name: workspaceSlug
required: true
schema:
type: string
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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-visibility:
patch:
operationId: updatePublicVisibility
parameters:
- description: Workspace slug
in: path
name: workspaceSlug
required: true
schema:
type: string
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateWorkspacePublicVisibilityRequest"
required: true
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/Workspace"
description: Workspace updated
summary: Toggle public visibility for a workspace
tags:
- workspace
/workspaces/{workspaceSlug}/repositories:
delete:
operationId: removeRepositoryToMonitor
parameters:
- description: Workspace slug
in: path
name: workspaceSlug
required: true
schema:
type: string
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
responses:
"200":
content:
application/json:
schema:
type: array
items:
type: string
description: Repository list
security: []
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
responses:
"200":
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/TeamInfo"
description: list of teams with their members and permissions
security: []
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
security: []
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
security: []
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
security: []
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
- 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
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
responses:
"200":
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/UserTeams"
description: OK
security: []
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
ActivityBucket:
type: object
description: Activity in one time bucket of a range
properties:
start:
type: string
format: date-time
description: "When the bucket starts: midnight of its day, of its week's\
\ Monday or of its month's first day, in the requested time zone. The\
\ first bucket may start before the range."
summary:
$ref: "#/components/schemas/ActivitySummary"
description: The activity in the bucket that falls within the range
required:
- start
- summary
ActivityOverview:
type: object
description: "Activity in a time range, in total and over time"
properties:
bucket:
$ref: "#/components/schemas/TimeBucketSize"
description: How long each bucket is
buckets:
type: array
description: "Every bucket the range touches, oldest first, including those\
\ without activity"
items:
$ref: "#/components/schemas/ActivityBucket"
summary:
$ref: "#/components/schemas/ActivitySummary"
description: The activity in the range; the buckets' summaries add up to
it
required:
- bucket
- buckets
- summary
ActivitySummary:
type: object
description: Counts of activity in a time range. Each count is the sum of that
kind's counts in the work list for the same scope and range.
properties:
approvals:
type: integer
format: int32
description: Reviews that approved
example: 4
changeRequests:
type: integer
format: int32
description: Reviews that requested changes
example: 1
codeComments:
type: integer
format: int32
description: Comments on lines of code
example: 12
commentReviews:
type: integer
format: int32
description: Reviews that only commented
example: 2
comments:
type: integer
format: int32
description: Comments in pull request and issue conversations
example: 9
issuesClosed:
type: integer
format: int32
description: Issues closed; a closed issue counts for its author
example: 1
issuesOpened:
type: integer
format: int32
description: Issues opened
example: 2
pullRequestsClosed:
type: integer
format: int32
description: Pull requests closed without merging
example: 1
pullRequestsMerged:
type: integer
format: int32
description: Pull requests merged; a merge counts for the pull request's
author
example: 3
pullRequestsOpened:
type: integer
format: int32
description: Pull requests opened
example: 4
required:
- approvals
- changeRequests
- codeComments
- commentReviews
- comments
- issuesClosed
- issuesOpened
- pullRequestsClosed
- pullRequestsMerged
- pullRequestsOpened
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: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
- 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: URL-friendly identifier for the workspace
example: my-workspace
minLength: 1
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
required:
- accountLogin
- accountType
- displayName
- kind
- workspaceSlug
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
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
- 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
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 keeps holding
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:
REDIRECT — OAuth / App-install flows (GitHub, Slack). vendorUrl is the
URL to bounce the browser to; the signed OAuth state is already embedded in it.LINKED — inline-credential flows (GitLab PAT). connectionId is the
newly-created Connection; no further round-trip is needed.Deliberately a flat record (nullable per-variant fields) rather than a sealed
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
UpdateWorkspacePublicVisibilityRequest:
type: object
description: Request to update workspace public visibility setting
properties:
isPubliclyViewable:
type: boolean
description: Whether the workspace should be publicly viewable without authentication
required:
- isPubliclyViewable
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
isPubliclyViewable:
type: boolean
description: Whether the workspace is publicly viewable without authentication
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
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
workspaceSlug:
type: string
description: URL-friendly identifier for the workspace
example: my-workspace
required:
- accountLogin
- createdAt
- displayName
- gitlabWebhookRegistered
- hasPersonalAccessToken
- hasSlackToken
- id
- isPubliclyViewable
- practiceReviewAutoTriggerEnabled
- practiceReviewManualTriggerEnabled
- practicesEnabled
- status
- updatedAt
- 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
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
status:
type: string
description: "Current lifecycle status of the workspace (PENDING, ACTIVE,\
\ ARCHIVED)"
workspaceSlug:
type: string
description: URL-friendly identifier for the workspace
example: my-workspace
required:
- accountLogin
- createdAt
- displayName
- id
- practicesEnabled
- status
- 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. 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
MemberActivity:
type: object
description: One member and their activity in a time range
properties:
summary:
$ref: "#/components/schemas/ActivitySummary"
description: The member's activity
user:
$ref: "#/components/schemas/UserInfo"
description: The member
required:
- summary
- user
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
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<=nFAILED"
enum:
- RATE_LIMITED
- UNAVAILABLE
- MALFORMED
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
status:
type: string
description: the verdict an administrator reads first
enum:
- DISABLED
- NOT_APPLICABLE
- NEVER_CHECKED
- CURRENT
- UPDATE_AVAILABLE
- FAILED
required:
- running
- status
RenameWorkspaceSlugRequest:
type: object
description: Request to rename a workspace's URL slug
properties:
newSlug:
type: string
description: New URL-friendly identifier for the workspace
example: new-workspace-slug
minLength: 1
pattern: "^[a-z0-9][a-z0-9-]{2,50}$"
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
- 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
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
- 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
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
- 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
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
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
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
status:
type: string
enum:
- QUEUED
- RUNNING
- COMPLETED
- FAILED
- TIMED_OUT
- CANCELLED
target:
$ref: "#/components/schemas/ReviewRunTarget"
required:
- createdAt
- feedback
- id
- observations
- 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
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
- 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"
required:
- hidden
- id
- labels
- members
- membershipCount
- name
- repoPermissionCount
- repositories
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.
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
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"
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
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
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