Skip to content

HTTP API / Operations

Operations API ​

26 operations. Paths are relative to the API host (http://localhost:5080 in local development). Every operation accepts an OIDC bearer token (Authorization: Bearer …) or a workspace API key (X-Api-Key: keel_live_…); errors are RFC 9457 Problem Details with a code (error codes). Permissions: matrix.

MethodPathSummary
GET/api/v1/ops/exports/{fileName}Download a tenant export written by offboarding (operators; the export folder must be shared with the worker).
GET/api/v1/ops/healthComponent health (the public /status document) for the console.
GET/api/v1/ops/leadsDemo requests from the website, newest first, received in [from, to); cursor paging. Never older than the 24-month retention.
GET/api/v1/ops/leads:exportCSV of the demo requests matching from/to (at most 10,000, newest first). Recorded in the operator log with the count only.
GET/api/v1/ops/logThe operator log, newest first: offboarding tombstones, exports, support sessions.
GET/api/v1/ops/meThe signed-in platform operator and their platform role, owner or operator (403 for everyone else).
GET/api/v1/ops/overviewCustomer tenants by plan and status, trials and contracts ending, usage at 80% of a limit or more, estimated monthly recurring revenue from list prices and new tenants per week. Internal tenants are left out.
GET/api/v1/ops/platform-membersThe platform owner and operators (operators; read-only for everyone but the owner).
POST/api/v1/ops/platform-membersOwner: invite an operator by email. The IdP emails them a link to set a password and an authenticator app.
DELETE/api/v1/ops/platform-members/{memberId}Owner: remove an operator. Their platform access and open support sessions end at once.
POST/api/v1/ops/platform-members/{memberId}:transfer-ownershipOwner: hand platform ownership to an operator (type their email to confirm). You stay an operator.
PUT/api/v1/ops/platform-members/{memberId}/required-amrOwner: require a sign-in method (token amr, e.g. hwk or otp) for one member, or clear it with null.
POST/api/v1/ops/status/incidentsOperators: open an incident or maintenance on the status page; confirmed subscribers are emailed.
POST/api/v1/ops/status/incidents/{incidentId}/updatesOperators: post an update to an open incident (Resolved closes it); confirmed subscribers are emailed.
POST/api/v1/ops/support-sessions/{sessionId}:endEnd a support session.
GET/api/v1/ops/tenantsEvery tenant with plan, region, licensed modules, usage counts, last activity and support consent.
POST/api/v1/ops/tenantsProvision a customer tenant: its first workspace, a trial or a contract, and an Owner invitation emailed to the first Owner. The operator does not become a member. 200 with the existing tenant when the slug was already provisioned for the same first Owner.
GET/api/v1/ops/tenants/{tenantId}One tenant: identity, usage, billing (plan, contract, trial, internal), the first-Owner invitation and any scheduled deletion.
POST/api/v1/ops/tenants/{tenantId}:cancel-offboardingCancel a tenant's scheduled deletion within its grace period (audited in the customer's log).
POST/api/v1/ops/tenants/{tenantId}:extend-trialExtend the tenant's Keel trial by 1–90 days (while it runs or within 30 days of its end; at most 90 days from its start). An ended trial becomes writable again.
POST/api/v1/ops/tenants/{tenantId}:offboardOffboard a tenant: scheduled 7 days out (read-only, Owners emailed, cancellable), or now with a reason; then an optional export and a verified hard delete of all its data (a platform job).
PUT/api/v1/ops/tenants/{tenantId}/contractPut the tenant on a contract: plan, add-ons, limit overrides (null = unlimited), end date and annual value (USD). Usage over the new limits comes back as warnings.
PUT/api/v1/ops/tenants/{tenantId}/internalMark the tenant internal (excluded from customer metrics; no trial expiry, no billing notices) or a customer again.
POST/api/v1/ops/tenants/{tenantId}/owner-invitation:resendEmail the first-Owner invitation again with a new link (the previous link stops working), valid for 7 days.
POST/api/v1/ops/tenants/{tenantId}/owner-invitation:revokeWithdraw the pending first-Owner invitation; its link stops working.
POST/api/v1/ops/tenants/{tenantId}/support-sessionsStart a read-only support session in a tenant that granted consent (403 Support.NoConsent otherwise).

DownloadTenantExport ​

http
GET /api/v1/ops/exports/{fileName}

Download a tenant export written by offboarding (operators; the export folder must be shared with the worker).

ParameterInTypeRequiredNotes
fileNamepathstringyes
StatusDescriptionBody
200OK—
403ForbiddenProblemDetails

GetOperatorHealth ​

http
GET /api/v1/ops/health

Component health (the public /status document) for the console.

StatusDescriptionBody
200OKPlatformStatusDto

Response 200: PlatformStatusDto

FieldTypeNotes
componentsStatusComponentDto[]
generatedAtdate-time
statusstringThe worst component status (unknown components do not count).

ListLeads ​

http
GET /api/v1/ops/leads

Demo requests from the website, newest first, received in [from, to); cursor paging. Never older than the 24-month retention.

ParameterInTypeRequiredNotes
fromquerydate-timeno
toquerydate-timeno
cursorquerystringno
limitqueryint32no
StatusDescriptionBody
200OKLeadPageDto

Response 200: LeadPageDto

FieldTypeNotes
itemsLeadDto[]
nextCursorstring?

ExportLeads ​

http
GET /api/v1/ops/leads:export

CSV of the demo requests matching from/to (at most 10,000, newest first). Recorded in the operator log with the count only.

ParameterInTypeRequiredNotes
fromquerydate-timeno
toquerydate-timeno
StatusDescriptionBody
200OKstring
400Bad RequestProblemDetails
403ForbiddenProblemDetails

ListOperatorLog ​

http
GET /api/v1/ops/log

The operator log, newest first: offboarding tombstones, exports, support sessions.

ParameterInTypeRequiredNotes
limitqueryint32no
StatusDescriptionBody
200OKOperatorLogDto[]

GetOperatorIdentity ​

http
GET /api/v1/ops/me

The signed-in platform operator and their platform role, owner or operator (403 for everyone else).

StatusDescriptionBody
200OKOperatorIdentityResponse
403ForbiddenProblemDetails

Response 200: OperatorIdentityResponse

FieldTypeNotes
namestring
rolestringM12.4: owner or operator.
subjectstring

GetOperatorOverview ​

http
GET /api/v1/ops/overview

Customer tenants by plan and status, trials and contracts ending, usage at 80% of a limit or more, estimated monthly recurring revenue from list prices and new tenants per week. Internal tenants are left out.

StatusDescriptionBody
200OKOperatorOverviewDto

Response 200: OperatorOverviewDto

FieldTypeNotes
byPlanPlanCountDto[]
byStatusOverviewStatusCountsDto
contractsEndingContractEndingDto[]
customerTenantsint32
generatedAtdate-time
internalTenantsint32
limitAlertsLimitAlertDto[]
newTenantsPerWeekWeeklyCountDto[]
revenueRevenueEstimateDto
trialsEndingTrialEndingDto[]
trialsEndingIn14Daysint32
trialsEndingIn7Daysint32

ListPlatformMembers ​

http
GET /api/v1/ops/platform-members

The platform owner and operators (operators; read-only for everyone but the owner).

StatusDescriptionBody
200OKPlatformMemberDto[]

InvitePlatformOperator ​

http
POST /api/v1/ops/platform-members

Owner: invite an operator by email. The IdP emails them a link to set a password and an authenticator app.

Request body (application/json): InvitePlatformOperatorRequest

FieldTypeNotes
displayNamestring?
emailstring
requiredAmrstring?
StatusDescriptionBody
200OKPlatformOperatorInvitedDto

Response 200: PlatformOperatorInvitedDto

FieldTypeNotes
emailedboolean
memberPlatformMemberDto

RemovePlatformOperator ​

http
DELETE /api/v1/ops/platform-members/{memberId}

Owner: remove an operator. Their platform access and open support sessions end at once.

ParameterInTypeRequiredNotes
memberIdpathuuidyes
StatusDescriptionBody
204No Content—

TransferPlatformOwnership ​

http
POST /api/v1/ops/platform-members/{memberId}:transfer-ownership

Owner: hand platform ownership to an operator (type their email to confirm). You stay an operator.

ParameterInTypeRequiredNotes
memberIdpathuuidyes

Request body (application/json): TransferPlatformOwnershipRequest

FieldTypeNotes
confirmEmailstring
StatusDescriptionBody
204No Content—

SetPlatformMemberRequiredAmr ​

http
PUT /api/v1/ops/platform-members/{memberId}/required-amr

Owner: require a sign-in method (token amr, e.g. hwk or otp) for one member, or clear it with null.

ParameterInTypeRequiredNotes
memberIdpathuuidyes

Request body (application/json): SetRequiredAmrRequest

FieldTypeNotes
requiredAmrstring?
StatusDescriptionBody
200OKPlatformMemberDto

Response 200: PlatformMemberDto

FieldTypeNotes
addedAtdate-time
addedBystring
displayNamestring?
emailstring?
iduuid
requiredAmrstring?
rolestring
subjectstring

CreateStatusIncident ​

http
POST /api/v1/ops/status/incidents

Operators: open an incident or maintenance on the status page; confirmed subscribers are emailed.

Request body (application/json): CreateStatusIncidentRequest

FieldTypeNotes
componentsstring[]
impactStatusPageIncidentImpactOne of Maintenance, Minor, Major
messagestring
statusStatusPageIncidentStatusOne of Investigating, Identified, Monitoring, Resolved
titlestring
StatusDescriptionBody
201CreatedStatusIncidentDto

Response 201: StatusIncidentDto

FieldTypeNotes
componentsstring[]
iduuid
impactStatusPageIncidentImpactOne of Maintenance, Minor, Major
resolvedAtdate-time?
startedAtdate-time
statusStatusPageIncidentStatusOne of Investigating, Identified, Monitoring, Resolved
titlestring
updatesStatusIncidentUpdateDto[]

PostStatusIncidentUpdate ​

http
POST /api/v1/ops/status/incidents/{incidentId}/updates

Operators: post an update to an open incident (Resolved closes it); confirmed subscribers are emailed.

ParameterInTypeRequiredNotes
incidentIdpathuuidyes

Request body (application/json): PostStatusIncidentUpdateRequest

FieldTypeNotes
messagestring
statusStatusPageIncidentStatusOne of Investigating, Identified, Monitoring, Resolved
StatusDescriptionBody
200OKStatusIncidentDto

Response 200: StatusIncidentDto

FieldTypeNotes
componentsstring[]
iduuid
impactStatusPageIncidentImpactOne of Maintenance, Minor, Major
resolvedAtdate-time?
startedAtdate-time
statusStatusPageIncidentStatusOne of Investigating, Identified, Monitoring, Resolved
titlestring
updatesStatusIncidentUpdateDto[]

EndSupportSession ​

http
POST /api/v1/ops/support-sessions/{sessionId}:end

End a support session.

ParameterInTypeRequiredNotes
sessionIdpathuuidyes
StatusDescriptionBody
204No Content—

ListOperatorTenants ​

http
GET /api/v1/ops/tenants

Every tenant with plan, region, licensed modules, usage counts, last activity and support consent.

StatusDescriptionBody
200OKOperatorTenantDto[]

ProvisionTenant ​

http
POST /api/v1/ops/tenants

Provision a customer tenant: its first workspace, a trial or a contract, and an Owner invitation emailed to the first Owner. The operator does not become a member. 200 with the existing tenant when the slug was already provisioned for the same first Owner.

Request body (application/json): ProvisionTenantRequest

FieldTypeNotes
contractContractTermsInput?
firstOwnerEmailstring
firstWorkspaceNamestring?The first workspace's name; the tenant's name when left out.
internalboolean?
namestring
regionstringUS or EU.
slugstring
StatusDescriptionBody
200OKProvisionedTenantDto
201CreatedProvisionedTenantDto

Response 200: ProvisionedTenantDto

FieldTypeNotes
billingOperatorTenantBillingDto?
createdboolean
invitationIduuid
tenantIduuid
workspaceIduuid

GetOperatorTenant ​

http
GET /api/v1/ops/tenants/{tenantId}

One tenant: identity, usage, billing (plan, contract, trial, internal), the first-Owner invitation and any scheduled deletion.

ParameterInTypeRequiredNotes
tenantIdpathuuidyes
StatusDescriptionBody
200OKOperatorTenantDetailDto

Response 200: OperatorTenantDetailDto

FieldTypeNotes
billingOperatorTenantBillingDto?
contractOptionsContractOptionsDto
deletionTenantDeletionDto?
ownerInvitationFoundingInvitation?
tenantOperatorTenantDto

CancelTenantOffboarding ​

http
POST /api/v1/ops/tenants/{tenantId}:cancel-offboarding

Cancel a tenant's scheduled deletion within its grace period (audited in the customer's log).

ParameterInTypeRequiredNotes
tenantIdpathuuidyes
StatusDescriptionBody
200OKTenantDeletionDto

Response 200: TenantDeletionDto

FieldTypeNotes
exportboolean
iduuid
purgeJobIduuid?
requestedAtdate-time
requestedByNamestring
requestedByTypestring
scheduledFordate-time

ExtendTenantTrial ​

http
POST /api/v1/ops/tenants/{tenantId}:extend-trial

Extend the tenant's Keel trial by 1–90 days (while it runs or within 30 days of its end; at most 90 days from its start). An ended trial becomes writable again.

ParameterInTypeRequiredNotes
tenantIdpathuuidyes

Request body (application/json): ExtendTrialRequest

FieldTypeNotes
daysint32
StatusDescriptionBody
200OKOperatorTenantBillingDto

Response 200: OperatorTenantBillingDto

FieldTypeNotes
addOnsstring[]
annualValueUsdnumber?
endsOndate?
limitOverridesobject
limitsobject
planstring
readOnlyboolean
sourcestring
statusstring
trialEndsAtdate-time?
trialStartedAtdate-time?
warningsstring[]

OffboardTenant ​

http
POST /api/v1/ops/tenants/{tenantId}:offboard

Offboard a tenant: scheduled 7 days out (read-only, Owners emailed, cancellable), or now with a reason; then an optional export and a verified hard delete of all its data (a platform job).

ParameterInTypeRequiredNotes
tenantIdpathuuidyes

Request body (application/json): OffboardTenantRequest

FieldTypeNotes
confirmSlugstring
exportboolean
immediateboolean?Skip the 7-day grace period (legal or abuse cases); needs Reason.
reasonstring?
StatusDescriptionBody
202AcceptedOffboardingQueuedDto

Response 202: OffboardingQueuedDto

FieldTypeNotes
jobIduuid
scheduledFordate-time?
slugstring
tenantIduuid

SetTenantContract ​

http
PUT /api/v1/ops/tenants/{tenantId}/contract

Put the tenant on a contract: plan, add-ons, limit overrides (null = unlimited), end date and annual value (USD). Usage over the new limits comes back as warnings.

ParameterInTypeRequiredNotes
tenantIdpathuuidyes

Request body (application/json): ContractTermsInput

FieldTypeNotes
addOnsstring[]?
annualValueUsdnumber?
endsOndate?
limitOverridesobject?
planstring
StatusDescriptionBody
200OKOperatorTenantBillingDto

Response 200: OperatorTenantBillingDto

FieldTypeNotes
addOnsstring[]
annualValueUsdnumber?
endsOndate?
limitOverridesobject
limitsobject
planstring
readOnlyboolean
sourcestring
statusstring
trialEndsAtdate-time?
trialStartedAtdate-time?
warningsstring[]

SetTenantInternal ​

http
PUT /api/v1/ops/tenants/{tenantId}/internal

Mark the tenant internal (excluded from customer metrics; no trial expiry, no billing notices) or a customer again.

ParameterInTypeRequiredNotes
tenantIdpathuuidyes

Request body (application/json): SetTenantInternalRequest

FieldTypeNotes
internalboolean
StatusDescriptionBody
200OKOperatorTenantDto

Response 200: OperatorTenantDto

FieldTypeNotes
createdAtdate-time
deletionScheduledFordate-time?
featuresstring[]
iduuid
internalboolean
lastActivityAtdate-time?
membersint32
modelsint32
modulesstring[]
namestring
planstring
regionstring
slugstring
sourcesint32
statusstring
supportAccessExpiresAtdate-time?
workspacesint32

ResendOwnerInvitation ​

http
POST /api/v1/ops/tenants/{tenantId}/owner-invitation:resend

Email the first-Owner invitation again with a new link (the previous link stops working), valid for 7 days.

ParameterInTypeRequiredNotes
tenantIdpathuuidyes
StatusDescriptionBody
200OKFoundingInvitation

Response 200: FoundingInvitation

FieldTypeNotes
acceptedAtdate-time?
emailstring
expiresAtdate-time
iduuid
invitedBystring?
revokedAtdate-time?
statusstring

RevokeOwnerInvitation ​

http
POST /api/v1/ops/tenants/{tenantId}/owner-invitation:revoke

Withdraw the pending first-Owner invitation; its link stops working.

ParameterInTypeRequiredNotes
tenantIdpathuuidyes
StatusDescriptionBody
200OKFoundingInvitation

Response 200: FoundingInvitation

FieldTypeNotes
acceptedAtdate-time?
emailstring
expiresAtdate-time
iduuid
invitedBystring?
revokedAtdate-time?
statusstring

StartSupportSession ​

http
POST /api/v1/ops/tenants/{tenantId}/support-sessions

Start a read-only support session in a tenant that granted consent (403 Support.NoConsent otherwise).

ParameterInTypeRequiredNotes
tenantIdpathuuidyes

Request body (application/json): StartSupportSessionRequest

FieldTypeNotes
reasonstring
StatusDescriptionBody
200OKStartedSupportSessionDto

Response 200: StartedSupportSessionDto

FieldTypeNotes
expiresAtdate-time
sessionIduuid
tenantIduuid
tenantNamestring

Anchor Keel is a working product name: one platform, a shared core and licensed modules (Keel Semantic, Keel Migrate). Documentation built from the repository — facts are derived from code, ADRs and the decisions log.