openapi: 3.1.0
info:
title: Silicon IAM API
version: 1.0.0
summary: Secure identity, organization governance, application login, and delegated access.
description: |
Normative public and privileged HTTP contract for Silicon IAM. PostgreSQL is
authoritative; webhook delivery never substitutes for online authorization.
Timestamps are UTC RFC 3339 values. One-time secret responses can be replayed
for ten minutes only by the same caller using the same route, request digest,
and Idempotency-Key.
IAM-managed six-digit OTPs expire after ten minutes. Signup, Carbon login,
invitation-join, and verified-channel step-up challenges allow ten failed
verifications, then enter a 60-second cooldown before the current unexpired
challenge receives a fresh ten-attempt window. Replacement codes inherit
the partial failed-attempt count or active cooldown.
contact: { email: auth@teamofsilicons.com }
servers:
- { url: 'https://backend.iam.teamofsilicons.com', description: Production }
tags:
- { name: System }
- { name: Carbon signup }
- { name: Carbon authentication }
- { name: Carbon account }
- { name: OAuth }
- { name: Organizations }
- { name: Memberships }
- { name: Invitations }
- { name: Silicons }
- { name: Tags }
- { name: Trust }
- { name: Governance }
- { name: SSO }
- name: Applications
description: >-
Applications are organization-owned. Non-platform Application management
requires a direct Carbon IAM bearer and current active owner/admin
membership in the Application's organization.
- name: OBO Access
description: >-
Strictly same-organization Application discovery, request-bound proof
exchange, and single-use audience verification.
- { name: Webhooks }
- name: Testing environments
description: >-
A testing environment is an organization-owned replica of Silicon IAM
running against a separate database and starting completely empty. Every
plane-selectable route accepts an `X-Testing-Environment-Key` header; supplying one
executes that request inside the named environment instead of production,
against the same contract. OTP delivery is suppressed and verification
accepts `000000`. Test webhook deliveries are explicitly marked and
carry their environment key. Organization-prefixed lifecycle routes in
this section always operate on production; the singular test-only routes
require the environment header.
- { name: Platform administration }
paths:
/healthz:
get:
tags: [System]
operationId: getLiveness
security: []
responses:
'200': { $ref: '#/components/responses/HealthOk' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/readyz:
get:
tags: [System]
operationId: getReadiness
description: >-
Verifies the production database schema and, when configured, the
shared testing database's base plus testing-overlay migration ledgers.
security: []
responses:
'200': { $ref: '#/components/responses/HealthOk' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/version:
get:
tags: [System]
operationId: negotiateApiVersion
summary: Negotiate a public API version before using any versioned route.
description: >-
The client advertises every API major it implements in descending
preference order. IAM selects the highest common version. Official
clients fail closed when no common version exists or the response does
not match the advertised intersection.
security: []
parameters:
- name: Silicon-IAM-Supported-API-Versions
in: header
required: true
description: Comma-separated distinct API majors in descending client preference order.
schema:
type: string
minLength: 2
maxLength: 255
pattern: '^v[1-9][0-9]{0,8}(, *v[1-9][0-9]{0,8}){0,15}$'
responses:
'200':
description: The client and server agreed on the highest common API version.
headers:
Silicon-IAM-API-Version:
required: true
schema: { type: string, pattern: '^v[1-9][0-9]{0,8}$' }
Vary:
required: true
schema: { const: Silicon-IAM-Supported-API-Versions }
content:
application/json:
schema: { $ref: '#/components/schemas/ApiVersionNegotiation' }
'406': { $ref: '#/components/responses/NotAcceptable' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
/api/v1/version:
get:
tags: [System]
operationId: getVersion
security: []
responses:
'200':
description: Running contract and build version.
content:
application/json:
schema: { $ref: '#/components/schemas/VersionInfo' }
/api/v1/signup/sessions:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon signup]
operationId: createSignupSession
security: []
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
responses:
'201':
description: Signup session created for 48 hours.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/AuthSession' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/signup/sessions/{session_id}/email:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon signup]
operationId: sendSignupEmailCode
security: []
parameters:
- { $ref: '#/components/parameters/SessionId' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/EmailInput' }
responses:
'202': { $ref: '#/components/responses/CodeDispatchAccepted' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/signup/sessions/{session_id}/email/verify:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon signup]
operationId: verifySignupEmail
security: []
parameters:
- { $ref: '#/components/parameters/SessionId' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody: { $ref: '#/components/requestBodies/VerificationCode' }
responses:
'200': { $ref: '#/components/responses/Verified' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/signup/sessions/{session_id}/phone:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon signup]
operationId: sendSignupPhoneCode
security: []
parameters:
- { $ref: '#/components/parameters/SessionId' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PhoneInput' }
responses:
'202': { $ref: '#/components/responses/CodeDispatchAccepted' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/signup/sessions/{session_id}/phone/verify:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon signup]
operationId: verifySignupPhone
security: []
parameters:
- { $ref: '#/components/parameters/SessionId' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody: { $ref: '#/components/requestBodies/VerificationCode' }
responses:
'200': { $ref: '#/components/responses/Verified' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/signup/sessions/{session_id}/complete:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon signup]
operationId: completeCarbonSignup
security: []
parameters:
- { $ref: '#/components/parameters/SessionId' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CarbonSignupComplete' }
responses:
'201':
description: Carbon created after verified identities are rechecked atomically.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/CarbonSelf' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/carbon-ids/{carbon_id}/availability:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Carbon signup]
operationId: checkCarbonIdAvailability
security: []
parameters: [{ $ref: '#/components/parameters/CarbonIdPath' }]
responses:
'200':
description: Current availability; this does not reserve the handle.
content:
application/json:
schema: { $ref: '#/components/schemas/Availability' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/carbons/search:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Carbon account]
operationId: searchCarbons
security: [{ iamBearer: [] }]
parameters:
- { name: q, in: query, required: true, schema: { type: string, minLength: 1, maxLength: 100 } }
- { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 10, default: 10 } }
responses:
'200':
description: Zero to ten fuzzy Carbon ID suggestions; no profile or contact data is returned.
content:
application/json:
schema:
type: object
required: [items]
properties:
items: { type: array, maxItems: 10, items: { $ref: '#/components/schemas/CarbonSuggestion' } }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/carbons/resolve/email:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon account]
operationId: resolveCarbonByEmail
description: Resolve an exact active verified email to its Carbon ID. Only an authenticated direct Carbon may call this endpoint.
security: [{ iamBearer: [] }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/EmailInput' }
responses:
'200':
description: Exact active Carbon identity resolved.
content:
application/json:
schema: { $ref: '#/components/schemas/CarbonResolution' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/carbons/resolve/phone:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon account]
operationId: resolveCarbonByPhone
description: Resolve an exact active verified phone number to its Carbon ID. Only an authenticated direct Carbon may call this endpoint.
security: [{ iamBearer: [] }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PhoneInput' }
responses:
'200':
description: Exact active Carbon identity resolved.
content:
application/json:
schema: { $ref: '#/components/schemas/CarbonResolution' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/login:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Login]
operationId: startLogin
summary: Sign in, and mint a short-lived token for an application.
description: |
Naming an `app_id` makes this a login on that application's behalf and
produces a short-lived token; omitting it is an ordinary Silicon IAM
login and produces none. A `redirect_uri` decides delivery only: given
one, the token is appended to it as `slt` and the browser is sent there;
without one the token is rendered on a page, because there is nowhere to
send it. The token is valid for two minutes and for a single exchange.
security: [{ sessionCookie: [] }]
parameters:
- { name: app_id, in: query, schema: { $ref: '#/components/schemas/AppId' } }
- { name: redirect_uri, in: query, schema: { type: string, format: uri, maxLength: 2048 } }
- { name: org_id, in: query, schema: { $ref: '#/components/schemas/OrgId' } }
responses:
'200':
description: The short-lived token rendered as HTML, when no redirect URI was given.
content: { text/html: { schema: { type: string } } }
'302':
description: The given redirect URI with the short-lived token appended as `slt`.
headers: { Location: { schema: { type: string, format: uri } } }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/login/status:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Login]
operationId: readLoginStatus
summary: Report what became of a short-lived token that was shown.
description: |
The page that shows a token cannot run a script, so it carries a meta
refresh onto this route timed to the token's expiry. By then the token
has either been exchanged, and the login worked, or it has expired.
security: [{ sessionCookie: [] }]
parameters:
- { name: request, in: query, required: true, schema: { type: string, format: uuid } }
responses:
'200':
description: Whether the token was exchanged or expired, as HTML.
content: { text/html: { schema: { type: string } } }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/api/v1/app-auth/tokens:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Login]
operationId: exchangeApplicationToken
summary: Trade a short-lived token, or a refresh token, for a session.
description: |
The application authenticates itself the same way in both cases, so
which one it is asking for is simply which credential it presented.
Present exactly one of `slt` and `refresh_token`.
security: [{ applicationBasic: [] }]
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema: { $ref: '#/components/schemas/ApplicationTokenRequest' }
responses:
'200':
description: Opaque access token and rotating refresh token.
headers:
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/OAuthTokenResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/app-auth/short-lived-tokens:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Login]
operationId: issueShortLivedToken
summary: Get a short-lived token while already signed in.
description: |
For a caller that already holds a session -- a Silicon, which has no
browser to be redirected in, or a Carbon that should not have to start
another login. The token is valid for two minutes and for a single
exchange, and the application completes it at /api/v1/app-auth/tokens
exactly as it would one delivered through a redirect.
security: [{ bearerAuth: [] }]
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ShortLivedTokenRequest' }
responses:
'201':
description: The short-lived token and its lifetime in seconds.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ShortLivedToken' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/oauth/introspect:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [OAuth]
operationId: introspectOAuthToken
security: [{ applicationBasic: [] }]
parameters: [{ $ref: '#/components/parameters/OrgContext' }]
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema: { $ref: '#/components/schemas/TokenIntrospectionRequest' }
responses:
'200':
description: Activity after current revocation and membership checks.
content:
application/json:
schema: { $ref: '#/components/schemas/TokenIntrospection' }
'400':
description: The token-type hint or optional X-Org-ID header is malformed or duplicated.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
'401': { $ref: '#/components/responses/Unauthorized' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/oauth/revoke:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [OAuth]
operationId: revokeOAuthToken
description: |
Revoking an access token invalidates that token only. Revoking a refresh
token invalidates its complete refresh family and access authority issued
for the same Application session. Unknown tokens deliberately succeed.
security: [{ applicationBasic: [] }]
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema: { $ref: '#/components/schemas/OAuthRevocationRequest' }
responses:
'200':
description: Revocation accepted; unknown tokens also return 200.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/login/challenges:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon authentication]
operationId: createLoginChallenge
security: []
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/LoginChallengeCreate' }
responses:
'201':
description: Challenge created for an existing Carbon; Carbon-ID login may dispatch to both verified channels.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/AuthSession' }
'404':
description: No active Carbon exists for the submitted email, phone number, or Carbon ID.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/login/challenges/{session_id}/verify:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon authentication]
operationId: verifyLoginChallenge
security: []
parameters:
- { $ref: '#/components/parameters/SessionId' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody: { $ref: '#/components/requestBodies/VerificationCode' }
responses:
'200':
description: Carbon session established and every code in the challenge consumed.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/IamTokenResponse' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/step-up/challenges:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon authentication]
operationId: createStepUpChallenge
security: [{ iamBearer: [] }]
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/StepUpChallengeCreate' }
responses:
'201':
description: Reauthentication code sent to a verified channel.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/AuthSession' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/step-up/challenges/{session_id}/verify:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon authentication]
operationId: verifyStepUpChallenge
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/SessionId' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody: { $ref: '#/components/requestBodies/VerificationCode' }
responses:
'200':
description: Five-minute action-bound step-up token.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/StepUpTokenResponse' }
'401': { $ref: '#/components/responses/Unauthorized' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/auth/tokens/refresh:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon authentication]
operationId: refreshIamToken
security: []
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/RefreshTokenRequest' }
responses:
'200':
description: Rotated tokens; reuse of a consumed refresh token revokes its family.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/IamTokenResponse' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/logout:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon authentication]
operationId: logout
description: >-
Revokes the current session immediately by default. If all_sessions
would revoke another active session, every target and the authenticating
session must be at least 12 hours old and X-Step-Up-Token must carry a
verified-channel account.sessions_revoke_all assertion bound to the
current Carbon principal. Browser-cookie authentication additionally
requires X-CSRF-Token to exactly match the token bound into the signed
session cookie; bearer authentication does not. The operation fails
atomically if any active target is younger. A Carbon OAuth bearer may
also trigger logout only when its client is its audience; that form
revokes every IAM and Application authority bound to the parent session
across configured Applications and cannot select all_sessions.
security: [{ iamBearer: [] }, { sessionCookie: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- name: X-Step-Up-Token
in: header
required: false
description: Required only when all_sessions would revoke another active session.
schema: { type: string, pattern: '^sup_[A-Za-z0-9_-]{43}$' }
- name: X-CSRF-Token
in: header
required: false
description: Required only with sessionCookie authentication; it must exactly match the cookie-bound CSRF token.
schema: { type: string, minLength: 32, maxLength: 512 }
requestBody:
required: false
content:
application/json:
schema: { $ref: '#/components/schemas/LogoutRequest' }
responses:
'204':
description: Selected families revoked and application logout events queued.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/me:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Carbon account]
operationId: getCurrentCarbon
security: [{ iamBearer: [] }]
responses:
'200':
description: Current Carbon including self-only contact details.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/CarbonSelf' }
'401': { $ref: '#/components/responses/Unauthorized' }
patch:
tags: [Carbon account]
operationId: updateCurrentCarbon
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/merge-patch+json:
schema: { $ref: '#/components/schemas/CarbonProfilePatch' }
responses:
'200':
description: Profile updated.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/CarbonSelf' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/me/sessions:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Carbon account]
operationId: listCurrentCarbonSessions
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: Active and recently revoked session families.
content:
application/json:
schema: { $ref: '#/components/schemas/SessionPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
/api/v1/me/sessions/{session_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
delete:
tags: [Carbon account]
operationId: revokeCurrentCarbonSession
description: >-
Revokes one active session after it is at least 12 hours old. Revoking a
different session also requires the authenticating session to be at
least 12 hours old. X-Step-Up-Token must carry a verified-channel
account.session_revoke assertion bound to session_id. Immediate
current-session logout remains available through POST /api/v1/logout.
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/SessionId' }
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'204':
description: Session family revoked.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/me/login-history:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Carbon account]
operationId: listCurrentCarbonLoginHistory
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: User-wide and application login events.
content:
application/json:
schema: { $ref: '#/components/schemas/LoginEventPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
/api/v1/silicon-auth/token:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Carbon authentication, Silicons]
operationId: authenticateSilicon
security: []
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconAuthenticationRequest' }
responses:
'200':
description: Independently generated Silicon access and refresh tokens.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/IamTokenResponse' }
'401': { $ref: '#/components/responses/Unauthorized' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organization-ids/{org_id}/availability:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Organizations]
operationId: checkOrganizationIdAvailability
security: [{ iamBearer: [] }]
parameters: [{ $ref: '#/components/parameters/OrgIdPath' }]
responses:
'200':
description: Current availability; no reservation is created.
content:
application/json:
schema: { $ref: '#/components/schemas/Availability' }
'401': { $ref: '#/components/responses/Unauthorized' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Organizations]
operationId: listOrganizations
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
- { name: status, in: query, schema: { type: string, enum: [active, removed] } }
responses:
'200':
description: Organizations for the authenticated Carbon; Silicons are forbidden.
content:
application/json:
schema: { $ref: '#/components/schemas/OrganizationPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'429': { $ref: '#/components/responses/TooManyRequests' }
post:
tags: [Organizations]
operationId: createOrganization
security: [{ iamBearer: [] }]
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/OrganizationCreate' }
responses:
'201':
description: Organization and sole owner membership created atomically.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Organization' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}:
parameters: [{ $ref: '#/components/parameters/OrgIdPath' }, { $ref: '#/components/parameters/TestingEnvironmentSelection' }]
get:
tags: [Organizations]
operationId: getOrganization
security: [{ iamBearer: [] }]
responses:
'200':
description: Non-secret organization configuration visible to an active member.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/Organization' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
patch:
tags: [Organizations]
operationId: updateOrganization
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/merge-patch+json:
schema: { $ref: '#/components/schemas/OrganizationPatch' }
responses:
'200':
description: Organization updated; org_id is immutable.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Organization' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/ownership-transfers:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Organizations, Governance]
operationId: transferOrganizationOwnership
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/OwnershipTransfer' }
responses:
'200':
description: Owner swapped atomically; the previous owner becomes an admin with no delegated capabilities.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Organization' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/members:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Memberships]
operationId: listOrganizationMembers
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
- { name: principal_type, in: query, schema: { type: string, enum: [carbon, silicon] } }
- { name: tag_id, in: query, schema: { type: string, format: uuid } }
- { name: status, in: query, schema: { type: string, enum: [active, removed] } }
responses:
'200':
description: Typed membership directory page.
content:
application/json:
schema: { $ref: '#/components/schemas/MembershipPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/api/v1/organizations/{org_id}/members/{membership_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
get:
tags: [Memberships]
operationId: getOrganizationMember
security: [{ iamBearer: [] }]
responses:
'200':
description: Membership directory record.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/Membership' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
patch:
tags: [Memberships]
operationId: updateOrganizationMemberDirectory
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/merge-patch+json:
schema: { $ref: '#/components/schemas/MembershipDirectoryPatch' }
responses:
'200':
description: First Silicon, extra Silicons, profile data, or reporting line updated; tags and job_role use governed request workflows.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Membership' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
delete:
tags: [Memberships]
operationId: removeOrganizationMember
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
- name: reassign_reports_to
in: query
description: Required replacement Silicon membership when removing a Silicon with direct reports.
schema: { type: string, format: uuid }
responses:
'204':
description: Authority revoked immediately; membership identity and history are retained.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/members/{membership_id}/authorization:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
get:
tags: [Memberships, Governance]
operationId: getOrganizationMemberAuthorization
security: [{ iamBearer: [] }]
responses:
'200':
description: Organization tier, delegated capabilities, and authorization epoch.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/MembershipAuthorization' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/api/v1/organizations/{org_id}/members/{membership_id}/admin-promotions:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Memberships, Governance]
operationId: promoteOrganizationMemberToAdmin
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
responses:
'200':
description: Active Carbon member promoted to admin with no implicit capabilities.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/MembershipAuthorization' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/members/{membership_id}/admin-demotions:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Memberships, Governance]
operationId: demoteOrganizationAdmin
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
responses:
'200':
description: Admin demoted to member and all organization capabilities revoked.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/MembershipAuthorization' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/members/{membership_id}/capabilities:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
put:
tags: [Memberships, Governance]
operationId: replaceOrganizationMemberCapabilities
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/OrganizationCapabilitiesReplace' }
responses:
'200':
description: Explicit organization capabilities replaced without changing org_role.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/MembershipAuthorization' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/directory/self:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Memberships]
operationId: getOrganizationDirectorySelf
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/DirectoryFields' }
responses:
'200':
description: The requester's active organization-directory projection. Trust is evaluated only for Carbon-to-Silicon or Silicon-to-Silicon and is null for rows with no defined direction.
content:
application/json:
schema: { $ref: '#/components/schemas/DirectoryMember' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
/api/v1/organizations/{org_id}/directory/members:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Memberships]
operationId: listOrganizationDirectoryMembers
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/DirectoryFields' }
responses:
'200':
description: Active team members projected from the requester's point of view; trust is null for Carbon rows because Carbon-to-Carbon and Silicon-to-Carbon are undefined.
content:
application/json:
schema: { $ref: '#/components/schemas/DirectoryPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
/api/v1/organizations/{org_id}/directory/members/{membership_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Memberships]
operationId: getOrganizationDirectoryMember
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/DirectoryFields' }
responses:
'200':
description: One active team member projected from the requester's point of view; trust is null when the requester-to-row direction is undefined.
content:
application/json:
schema: { $ref: '#/components/schemas/DirectoryMember' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
/api/v1/organizations/{org_id}/carbon-invites:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Invitations]
operationId: listCarbonInvitations
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
- { name: status, in: query, schema: { $ref: '#/components/schemas/InviteStatus' } }
responses:
'200':
description: Invitations visible to the owner or callers with members.invite.
content:
application/json:
schema: { $ref: '#/components/schemas/InvitePage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
post:
tags: [Invitations]
operationId: createCarbonInvitation
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CarbonInviteCreate' }
responses:
'201':
description: 48-hour invitation created for an existing Carbon; org_role is always member.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Invite' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/carbon-invites/{invite_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/InviteIdPath' }
get:
tags: [Invitations]
operationId: getCarbonInvitation
security: [{ iamBearer: [] }]
responses:
'200':
description: Invitation with masked target identity.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/Invite' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
delete:
tags: [Invitations]
operationId: revokeCarbonInvitation
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
responses:
'204':
description: Pending invitation and its OTP challenges revoked.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/join/email-verification-code:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Invitations]
operationId: initiateEmailInvitationJoin
description: >-
An authenticated direct Carbon submits the invited email. The service
verifies that it is the exact active verified address immutably bound
when that Carbon's invitation was created and that a pending unexpired
invitation exists for this active email-join organization, then creates
a pending challenge and sends the six-digit Postmark OTP outside the
database transaction. The challenge becomes deliverable and the
endpoint succeeds only after provider confirmation. The
response exposes only the invitation ID needed by the join request and
the code lifetime, never contact data. Ten attempts per Carbon and
organization, including misses and varied emails, start a complete
60-second cooldown. A successful idempotent replay does not consume an
additional attempt.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/EmailInput' }
responses:
'202':
description: Matching invitation resolved and Postmark confirmed delivery acceptance for its replacement code.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/InvitationEmailCodeResponse' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404':
description: The authenticated Carbon has no matching usable invitation (`not_invited`).
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/organizations/{org_id}/join:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Invitations, Memberships]
operationId: joinOrganizationByEmailInvite
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/InvitationAcceptance' }
responses:
'200':
description: Membership created or deliberately reactivated with the invitation directory and trust snapshot applied atomically.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Membership' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/silicons:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Silicons]
operationId: listOrganizationSilicons
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
- { name: tag_id, in: query, schema: { type: string, format: uuid } }
responses:
'200':
description: Active Silicons in the organization.
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
post:
tags: [Silicons]
operationId: createSilicon
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconCreate' }
responses:
'201':
description: Active Silicon profile and 32-hex-character raw token created; webhook configuration is independent.
headers:
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconCreated' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/silicons/{silicon_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/SiliconIdPath' }
get:
tags: [Silicons]
operationId: getSilicon
security: [{ iamBearer: [] }]
responses:
'200':
description: Silicon profile, immutable directory identity, and hierarchy level.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/Silicon' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
patch:
tags: [Silicons]
operationId: updateSilicon
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/merge-patch+json:
schema: { $ref: '#/components/schemas/SiliconPatch' }
responses:
'200':
description: Mutable profile or hierarchy fields updated; public IDs and job role remain unchanged.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Silicon' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
delete:
tags: [Silicons]
operationId: removeSilicon
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
- name: reassign_reports_to
in: query
description: Required replacement Silicon when direct reports exist.
schema: { type: string, format: uuid }
responses:
'204':
description: 'Silicon disabled, credentials revoked, reports reassigned, and events queued.'
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/silicons/{silicon_id}/webhook:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/SiliconIdPath' }
get:
tags: [Silicons, Webhooks]
operationId: getSiliconWebhook
security: [{ iamBearer: [] }]
responses:
'200':
description: Active subscriber-managed endpoint. The signing secret is never returned by GET.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconWebhook' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
put:
tags: [Silicons, Webhooks]
operationId: replaceSiliconWebhook
description: >-
Configures or replaces the HTTPS endpoint and rotates its signing secret.
A Carbon manager must also present verified-channel step-up. If an active
endpoint already exists, If-Match is required; initial creation has no
existing representation and may omit it.
x-carbon-step-up-assurance: verified_channel
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- name: If-Match
in: header
required: false
description: Strong current endpoint ETag; required when replacing an existing endpoint.
schema: { type: string, pattern: '^"[0-9]+"$' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconWebhookReplace' }
responses:
'200':
description: Endpoint active; the new HMAC secret is shown only in this no-store response.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconWebhookConfigured' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
delete:
tags: [Silicons, Webhooks]
operationId: deleteSiliconWebhook
description: Disables the endpoint, retires its signing keys, and removes its subscription.
x-carbon-step-up-assurance: verified_channel
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
responses:
'204':
description: Endpoint disabled and subscription removed.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/silicons/{silicon_id}/webhook/dead-letters:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Silicons, Webhooks]
operationId: listSiliconWebhookDeadLetters
description: Lists only dead letters currently visible to this Silicon recipient or its authorized Carbon manager.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/SiliconIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: Recipient-scoped dead-letter page in reverse dead-letter order.
content:
application/json:
schema: { $ref: '#/components/schemas/WebhookDeadLetterPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/silicons/{silicon_id}/webhook/dead-letters/replays:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Silicons, Webhooks]
operationId: replaySiliconWebhookDeadLetters
description: >-
Reauthorizes the current endpoint and subscription, then requeues up to
100 exact deliveries in original event order using the current URL and
signing secret. Original event identity, payload, occurrence time,
aggregate version, and attempt history are preserved.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/SiliconIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/WebhookReplayRequest' }
responses:
'202':
description: Authorized dead letters were reset for ordered redelivery.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/WebhookReplayResponse' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/silicons/{silicon_id}/webhook/subscription:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/SiliconIdPath' }
get:
tags: [Silicons, Webhooks]
operationId: getSiliconWebhookSubscription
security: [{ iamBearer: [] }]
responses:
'200':
description: Active topic and tag-filter subscription.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconWebhookSubscription' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
put:
tags: [Silicons, Webhooks]
operationId: replaceSiliconWebhookSubscription
description: >-
Creates or replaces the subscription. An active endpoint must already
exist. A Carbon manager must also present verified-channel step-up. If a
subscription already exists, If-Match is required; initial creation may
omit it.
x-carbon-step-up-assurance: verified_channel
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- name: If-Match
in: header
required: false
description: Strong current subscription ETag; required when replacing an existing subscription.
schema: { type: string, pattern: '^"[0-9]+"$' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconWebhookSubscriptionReplace' }
responses:
'200':
description: Canonical subscription created or replaced.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconWebhookSubscription' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
delete:
tags: [Silicons, Webhooks]
operationId: deleteSiliconWebhookSubscription
description: Removes the subscription without changing the configured endpoint.
x-carbon-step-up-assurance: verified_channel
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
responses:
'204':
description: Subscription removed; delivery stops.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/silicons/{silicon_id}/token-rotation-requests:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Silicons, Governance]
operationId: requestSiliconTokenRotation
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/SiliconIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'201':
description: Immutable owner-approval request created.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApprovalRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/silicons/{silicon_id}/token-rotation-requests/{request_id}/complete:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Silicons, Governance]
operationId: completeSiliconTokenRotation
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/SiliconIdPath' }
- { $ref: '#/components/parameters/ApprovalRequestIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'200':
description: >-
Generates and reveals the replacement credential after approval has
already invalidated the old credential and revoked its session and
token authority.
headers:
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/SiliconTokenRotated' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/tags:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Tags]
operationId: listOrganizationTags
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: Normalized organization-scoped tags.
content:
application/json:
schema: { $ref: '#/components/schemas/TagPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
post:
tags: [Tags]
operationId: createOrganizationTag
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TagCreate' }
responses:
'201':
description: Tag created.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Tag' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/tags/{tag_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/TagIdPath' }
get:
tags: [Tags]
operationId: getOrganizationTag
security: [{ iamBearer: [] }]
responses:
'200':
description: Tag.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/Tag' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
patch:
tags: [Tags]
operationId: updateOrganizationTag
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/merge-patch+json:
schema: { $ref: '#/components/schemas/TagPatch' }
responses:
'200':
description: Tag renamed without changing its stable identifier.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Tag' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
delete:
tags: [Tags]
operationId: deleteOrganizationTag
security: [{ iamBearer: [] }]
description: >-
Deletes a tag. Requires `tags.manage`, which owners hold implicitly and
admins by grant. The tag stops existing for every caller: it leaves
listings and member projections immediately, stops conferring Silicon
access, and its name becomes available again. The cascade is atomic --
assignments are removed from every member who held it, tag-scoped trust
rules are archived, and the affected members' authorization epochs
advance so cached authority is invalidated at once. The removal is
recorded in each affected member's tag history and published as
`organization.tag_archived.v1`.
parameters:
- { $ref: '#/components/parameters/IfMatch' }
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'204':
description: Tag deleted.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/tags/{tag_id}/members:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Tags, Memberships]
operationId: listOrganizationTagMembers
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/TagIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: Carbon and Silicon memberships assigned to the tag.
content:
application/json:
schema: { $ref: '#/components/schemas/MembershipPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/api/v1/organizations/{org_id}/trust/default:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Trust]
operationId: getOrganizationDefaultTrust
security: [{ iamBearer: [] }]
parameters: [{ $ref: '#/components/parameters/OrgIdPath' }]
responses:
'200':
description: Organization default trust, initially internal/not_trusted.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/TrustValue' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
put:
tags: [Trust]
operationId: replaceOrganizationDefaultTrust
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TrustValue' }
responses:
'200':
description: Advisory default replaced.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TrustValue' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/trust/rules:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Trust]
operationId: listTrustRules
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: Typed advisory trust rules.
content:
application/json:
schema: { $ref: '#/components/schemas/TrustRulePage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
post:
tags: [Trust]
operationId: createTrustRule
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TrustRuleCreate' }
responses:
'201':
description: Advisory rule created.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TrustRule' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/trust/rules/{rule_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/TrustRuleIdPath' }
get:
tags: [Trust]
operationId: getTrustRule
security: [{ iamBearer: [] }]
responses:
'200':
description: Trust rule.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/TrustRule' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
patch:
tags: [Trust]
operationId: updateTrustRule
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/merge-patch+json:
schema: { $ref: '#/components/schemas/TrustRulePatch' }
responses:
'200':
description: Trust rule updated.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TrustRule' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
delete:
tags: [Trust]
operationId: deleteTrustRule
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
responses:
'204':
description: Rule deleted.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/trust/effective:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Trust]
operationId: evaluateEffectiveTrust
description: >-
Uses a Carbon subject's membership-wide default or the organization
default for a Silicon subject, then applies tag and exact-Silicon rules.
security: [{ iamBearer: [] }]
parameters: [{ $ref: '#/components/parameters/OrgIdPath' }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TrustEvaluationRequest' }
responses:
'200':
description: Advisory value and matching-rule explanation; never an authorization decision.
content:
application/json:
schema: { $ref: '#/components/schemas/TrustEvaluation' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
/api/v1/organizations/{org_id}/role-change-requests:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Governance]
operationId: createRoleChangeRequest
description: Only an active Silicon may create this governed request; regular Carbons use no request path.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/RoleChangeRequestCreate' }
responses:
'201':
description: Immutable approval request created with target-specific quorum.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApprovalRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
/api/v1/organizations/{org_id}/approval-requests:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Governance]
operationId: listApprovalRequests
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
- { name: status, in: query, schema: { $ref: '#/components/schemas/ApprovalStatus' } }
- { name: kind, in: query, schema: { $ref: '#/components/schemas/ApprovalKind' } }
- { name: actionable_by_me, in: query, schema: { type: boolean } }
responses:
'200':
description: Pending and historical requests visible to the caller.
content:
application/json:
schema: { $ref: '#/components/schemas/ApprovalRequestPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/api/v1/organizations/{org_id}/approval-requests/{request_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Governance]
operationId: getApprovalRequest
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/ApprovalRequestIdPath' }
responses:
'200':
description: Immutable request and collected decisions.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/ApprovalRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/api/v1/organizations/{org_id}/approval-requests/{request_id}/decisions:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Governance]
operationId: decideApprovalRequest
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/ApprovalRequestIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
- name: X-Step-Up-Token
in: header
required: false
description: Required with verified-channel assurance when deciding a Silicon token-rotation request.
schema: { type: string, pattern: '^sup_[A-Za-z0-9_-]{43}$' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ApprovalDecisionCreate' }
responses:
'200':
description: >-
Unique decision recorded. Terminal job-role/tag changes apply
exactly once. Approval of a Silicon credential rotation immediately
invalidates the old credential and its token/session authority but
does not generate the replacement secret.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApprovalRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/members/{membership_id}/job-role:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
put:
tags: [Governance]
operationId: replaceMemberJobRole
description: >-
A Carbon owner, or an admin with roles.approve, directly replaces the
descriptive job role for any active Carbon or Silicon and appends
immutable direct-actor history.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/DirectJobRoleReplace' }
responses:
'200':
description: Job role replaced directly and history appended.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Membership' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/members/{membership_id}/job-role-history:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Governance]
operationId: listMemberJobRoleHistory
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: Applied job-role changes and their approvers.
content:
application/json:
schema: { $ref: '#/components/schemas/RoleHistoryPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/api/v1/organizations/{org_id}/members/{membership_id}/tag-change-requests:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Governance]
operationId: createMemberTagChangeRequest
description: Only an active Silicon may request this tag-set change for an active Carbon or Silicon target.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TagChangeRequestCreate' }
responses:
'201':
description: >-
Immutable tag-change request created. Carbon targets require the
affected Carbon and an eligible owner/admin; Silicon targets
require an eligible owner/admin.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApprovalRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/members/{membership_id}/tags:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
put:
tags: [Governance, Tags]
operationId: replaceMemberTags
description: >-
A Carbon owner, or an admin with tags.manage, atomically replaces the
complete active tag set for any active Carbon or Silicon, advances its
authorization epoch, and appends immutable direct-actor history.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/DirectTagSetReplace' }
responses:
'200':
description: Complete membership tag set replaced directly.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Membership' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/organizations/{org_id}/members/{membership_id}/tag-history:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Governance]
operationId: listMemberTagHistory
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/MembershipIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: Applied membership tag sets with their requester and approvers.
content:
application/json:
schema: { $ref: '#/components/schemas/TagHistoryPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/api/v1/organizations/{org_id}/testing-environments:
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
get:
tags: [Testing environments]
operationId: listTestingEnvironments
security: [{ iamBearer: [] }]
description: Lists the organization's environments. Deleted environments are hidden unless `status` asks for them.
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentStatus' }
- { $ref: '#/components/parameters/TestingEnvironmentCursor' }
- { $ref: '#/components/parameters/TestingEnvironmentLimit' }
responses:
'200':
description: Environments owned by the organization.
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
post:
tags: [Testing environments]
operationId: createTestingEnvironment
security: [{ iamBearer: [] }]
description: >-
Creates an empty environment. Any active member may create one, Carbon
or Silicon, and becomes its creator with permanent administrative
authority over it. The key is returned here for convenience and stays
retrievable afterwards.
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentCreate' }
responses:
'201':
description: Environment created; the response carries its key.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentWithKey' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/organizations/{org_id}/testing-environments/{environment_id}:
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/TestingEnvironmentIdPath' }
get:
tags: [Testing environments]
operationId: getTestingEnvironment
security: [{ iamBearer: [] }]
responses:
'200':
description: Environment.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironment' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
patch:
tags: [Testing environments]
operationId: updateTestingEnvironment
security: [{ iamBearer: [] }]
description: Renames or re-describes a live environment. Restricted to its creator and to organization owners and admins.
parameters:
- { $ref: '#/components/parameters/IfMatch' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentPatch' }
responses:
'200':
description: Environment updated.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironment' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
delete:
tags: [Testing environments]
operationId: deleteTestingEnvironment
security: [{ iamBearer: [] }]
description: >-
Retires the environment. Nothing is erased yet: the record survives with
a `purge_after` deadline and can be restored until it passes, after
which the data is destroyed permanently.
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'200':
description: Environment retired and scheduled for purge.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironment' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/organizations/{org_id}/testing-environments/{environment_id}/key:
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/TestingEnvironmentIdPath' }
get:
tags: [Testing environments]
operationId: getTestingEnvironmentKey
security: [{ iamBearer: [] }]
description: >-
Returns the current environment key. Restricted to the environment's
creator and to organization owners and admins, and audited on every
read.
responses:
'200':
description: Current environment key.
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentKey' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/organizations/{org_id}/testing-environments/{environment_id}/key-rotations:
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/TestingEnvironmentIdPath' }
post:
tags: [Testing environments]
operationId: rotateTestingEnvironmentKey
security: [{ iamBearer: [] }]
description: Issues a new key and invalidates the previous one immediately.
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'200':
description: Key rotated; the response carries the new key.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentWithKey' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/organizations/{org_id}/testing-environments/{environment_id}/cleanings:
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/TestingEnvironmentIdPath' }
post:
tags: [Testing environments]
operationId: cleanTestingEnvironment
security: [{ iamBearer: [] }]
description: >-
Deletes every row the environment holds while keeping the environment
itself. The key is unchanged and the environment stays usable.
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'200':
description: Environment data erased.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentCleaning' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/organizations/{org_id}/testing-environments/{environment_id}/restorations:
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/TestingEnvironmentIdPath' }
post:
tags: [Testing environments]
operationId: restoreTestingEnvironment
security: [{ iamBearer: [] }]
description: >-
Brings a retired environment back before its `purge_after` deadline.
Conflicts when the name has been taken by another environment in the
meantime, or when the deadline has already passed.
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'200':
description: Environment restored.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironment' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/testing-environment:
get:
tags: [Testing environments]
operationId: describeCurrentTestingEnvironment
security: [{ testingEnvironmentKey: [] }]
description: >-
Describes the environment the presented key opens. Authorized by the
key alone, so it needs no IAM identity and discloses nothing about the
owning organization's members or production state.
responses:
'200':
description: The environment this key opens.
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentSelf' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/testing-environment/cleanings:
post:
tags: [Testing environments]
operationId: cleanCurrentTestingEnvironment
security: [{ testingEnvironmentKey: [] }]
description: >-
Deletes every row the environment holds, authorized by the key alone.
The key is the environment's root authority, and the data is disposable
by construction.
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'200':
description: Environment data erased.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingEnvironmentCleaning' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/testing-environment/applications/imports:
post:
tags: [Testing environments, Applications]
operationId: importTestingApplication
security: [{ iamBearer: [], testingEnvironmentKey: [] }]
description: >-
Imports one canonical production Application into the selected testing
environment. If its organization is absent there, IAM creates it and
makes the authenticated test Carbon its owner. The Application keeps
its production app_id, base_url, webhook URL, OBO surface, and inherited
webhook signing secret; that inherited secret is never returned. IAM
issues and returns a fresh test-only client secret.
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TestingApplicationImport' }
responses:
'201':
description: Production Application imported with a fresh test-only client secret.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestingApplicationImported' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'503': { $ref: '#/components/responses/ServiceUnavailable' }
/api/v1/organizations/{org_id}/sso:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [SSO]
operationId: getSsoConfiguration
security: [{ iamBearer: [] }]
parameters: [{ $ref: '#/components/parameters/OrgIdPath' }]
responses:
'200':
description: Non-secret WorkOS mapping, entitlement, connection, and join-method state.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/SsoConfiguration' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
delete:
tags: [SSO]
operationId: disableSsoConfiguration
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
responses:
'204':
description: Connection disabled after join_method is safely changed away from sso.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
/api/v1/organizations/{org_id}/sso/setup-link:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [SSO]
operationId: createSsoSetupLink
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'201':
description: Five-minute WorkOS Admin Portal setup link. The idempotency reservation commits before provider I/O; an in-flight identical key returns a retryable conflict and a completed response is replayable for five minutes.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/SsoSetupLink' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'502': { $ref: '#/components/responses/BadGateway' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/organizations/{org_id}/sso/authorize:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [SSO]
operationId: authorizeSsoJoin
security: [{ sessionCookie: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { name: return_to, in: query, schema: { type: string, format: uri } }
responses:
'302':
description: Validated redirect to WorkOS with state and nonce bound to the authenticated Carbon.
headers: { Location: { schema: { type: string, format: uri } } }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'502': { $ref: '#/components/responses/BadGateway' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/sso/callback:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [SSO]
operationId: handleSsoCallback
security: [{ sessionCookie: [] }]
parameters:
- { name: code, in: query, required: true, schema: { type: string, minLength: 1, maxLength: 2048 } }
- { name: state, in: query, required: true, schema: { type: string, minLength: 16, maxLength: 512 } }
responses:
'302':
description: Existing Carbon admitted or linked through the active tenant-bound WorkOS connection, using fixed conservative member defaults on admission or reactivation, then redirected only to the stored validated return URI.
headers: { Location: { schema: { type: string, format: uri } } }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'502': { $ref: '#/components/responses/BadGateway' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/organizations/{org_id}/sso/test:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [SSO]
operationId: testSsoConfiguration
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
responses:
'200':
description: Reads the exact provider organization and connection; succeeds only when the connection is active and belongs to the permanently mapped organization.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/TestResult' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'502': { $ref: '#/components/responses/BadGateway' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/api/v1/provider-webhooks/workos:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [SSO, Webhooks]
operationId: receiveWorkOsWebhook
security: [{ workosSignature: [] }]
requestBody:
required: true
content:
application/json:
schema: { type: object, additionalProperties: true, maxProperties: 100 }
responses:
'202': { description: 'Signature-valid, fresh, replay-safe event accepted idempotently.' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
'413': { $ref: '#/components/responses/PayloadTooLarge' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/applications:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Applications]
operationId: listApplications
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
- { name: status, in: query, schema: { $ref: '#/components/schemas/ApplicationStatus' } }
responses:
'200':
description: Applications owned by organizations in which the authenticated Carbon is a current active owner/admin.
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'429': { $ref: '#/components/responses/TooManyRequests' }
post:
tags: [Applications]
operationId: createApplication
security: [{ iamBearer: [] }]
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationCreate' }
responses:
'201':
description: >-
Verified organization-owned Application with canonical
`{org_id}>{handle}` id and discoverable base URL. IAM generates the
app secret and stores the caller-supplied webhook secret. The
response echoes the supplied webhook secret for v1 compatibility.
Current owner/admin authority is rechecked before creation or
secret replay.
headers:
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationCreated' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/application-directory/{app_id}:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Applications]
operationId: discoverApplicationBaseUrl
description: >-
Returns the public backend base URL of a verified Application. Any
authenticated Application may discover any other Application,
including one outside its organization. The caller is derived only
from HTTP Basic credentials. With an X-Testing-Environment-Key, both
the caller credential and target resolve exclusively inside that
environment.
security: [{ applicationBasic: [] }]
parameters: [{ $ref: '#/components/parameters/AppIdPath' }]
responses:
'200':
description: Canonical Application id and its configured base URL.
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationBaseUrl' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/applications/{app_id}:
parameters: [{ $ref: '#/components/parameters/AppIdPath' }, { $ref: '#/components/parameters/TestingEnvironmentSelection' }]
get:
tags: [Applications]
operationId: getApplication
security: [{ iamBearer: [] }]
responses:
'200':
description: Organization-owned manageable application without raw secrets.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/Application' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
patch:
tags: [Applications]
operationId: updateApplication
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/merge-patch+json:
schema: { $ref: '#/components/schemas/ApplicationPatch' }
responses:
'200':
description: Non-sensitive metadata updated; scope or redirect changes enter review before activation.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/Application' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/applications/{app_id}/client-secret-rotations:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Applications]
operationId: rotateApplicationClientSecret
description: >-
Atomically retires every prior usable client secret and reveals exactly
one active successor. Step-up action application.client_secret.rotate
is bound to the internal Application UUID. Exact idempotent replay may
recover the no-store response for ten minutes.
x-required-step-up-assurance: verified_channel
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/AppIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
responses:
'200':
description: Client secret rotated and shown once.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationSecretRotated' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/applications/{app_id}/webhook-secret-rotations:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Applications, Webhooks]
operationId: rotateApplicationWebhookSecret
description: >-
Atomically retires the current webhook signing secret and installs the
caller-supplied successor. New deliveries use the returned secret version;
already persisted in-flight deliveries retain their original signed
bytes and version. Exact idempotent replay may recover the no-store
response for ten minutes. Step-up action
application.webhook_secret.rotate is bound to the internal
Application UUID.
x-required-step-up-assurance: verified_channel
security: [{ iamBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/AppIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationWebhookSecretRotate' }
responses:
'200':
description: Caller-supplied webhook signing secret installed; the response echoes it for v1 compatibility.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationWebhookSecretRotated' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/applications/{app_id}/webhook:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Applications, Webhooks]
operationId: getApplicationWebhook
security: [{ iamBearer: [] }]
parameters: [{ $ref: '#/components/parameters/AppIdPath' }]
responses:
'200':
description: One active destination plus any pending reviewed replacement. The body version and ETag are the same application aggregate version.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationWebhook' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
put:
tags: [Applications, Webhooks]
operationId: proposeApplicationWebhookReplacement
description: >-
In production, validates and proposes a replacement for platform
review while the current endpoint remains active. In a testing
environment, which deliberately has no platform reviewer, atomically
retires the old endpoint and activates this replacement immediately.
Repeating the active or pending URL without a replacement secret, or
supplying the exact current URL and secret where they can be compared,
returns `409 application_webhook_unchanged` without changing the
Application version or emitting audit/outbox events.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/AppIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationWebhookReplace' }
responses:
'200':
description: >-
Testing-environment replacement activated immediately. When an
imported test Application still inherits its production signing
key, the request must provide a new test-only signing secret and
this response echoes it for v1 compatibility.
The body version and ETag are the same Application aggregate
version.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Cache-Control:
schema: { const: no-store }
description: Present when the response echoes a caller-supplied signing secret.
Pragma:
schema: { const: no-cache }
description: Present when the response echoes a caller-supplied signing secret.
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationWebhook' }
'202':
description: >-
HTTPS destination passed SSRF validation and awaits platform
review. Normally the active destination and signing secret are
unchanged. If the request supplies a replacement secret, IAM
installs it for the pending endpoint and echoes it for v1
compatibility. The body version and ETag are the same Application
aggregate version.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Cache-Control:
schema: { const: no-store }
description: Present when the response echoes a caller-supplied signing secret.
Pragma:
schema: { const: no-cache }
description: Present when the response echoes a caller-supplied signing secret.
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationWebhook' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/applications/{app_id}/webhook/dead-letters:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Applications, Webhooks]
operationId: listApplicationWebhookDeadLetters
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/AppIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: Application-recipient dead-letter page in reverse dead-letter order.
content:
application/json:
schema: { $ref: '#/components/schemas/WebhookDeadLetterPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/applications/{app_id}/webhook/dead-letters/replays:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Applications, Webhooks]
operationId: replayApplicationWebhookDeadLetters
description: >-
Reauthorizes current Application access, then requeues up to 100 exact
deliveries in original event order using the current endpoint and
signing secret while preserving immutable event and attempt history.
The secret-free session.logout.v1 revocation-control event instead
requires the exact persisted dead-letter recipient to remain bound to
this Application because logout itself revoked the delegated authority.
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/AppIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/WebhookReplayRequest' }
responses:
'202':
description: Authorized dead letters were reset for ordered redelivery.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/WebhookReplayResponse' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/applications/{app_id}/login-history:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Applications]
operationId: listApplicationLoginHistory
security: [{ iamBearer: [] }]
parameters:
- { $ref: '#/components/parameters/AppIdPath' }
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
responses:
'200':
description: App-specific authorization and token-exchange history.
content:
application/json:
schema: { $ref: '#/components/schemas/LoginEventPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/obo-access/applications/{app_id}/endpoints:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [OBO Access]
operationId: discoverApplicationOboEndpoints
description: >-
Returns the active callable endpoint catalog of a verified Application
in the authenticated Application's organization. Nonexistent,
unverified, and cross-organization targets all return the same 404.
security: [{ applicationBasic: [] }]
parameters:
- { $ref: '#/components/parameters/AppIdPath' }
responses:
'200':
description: Same-organization Application reference and its active endpoints in endpoint_id order.
content:
application/json:
schema: { $ref: '#/components/schemas/OboEndpointCatalog' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/obo-access/exchanges:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [OBO Access]
operationId: exchangeOboAccessProof
description: >-
Authenticates App A with HTTP Basic and a fresh request HMAC. IAM
derives the tenant from App A, requires audience App B and the subject
membership to belong to that same organization, loads registered_path
from the selected active endpoint, and verifies X-OBO-Signature in
constant time over
timestamp.method.registered_path.body_sha256.Idempotency-Key. The
request carries only metadata and the body digest, never the downstream
body or file. Exact idempotent replay expires no later than the proof.
security: [{ applicationBasic: [] }]
parameters:
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/OboTimestamp' }
- { $ref: '#/components/parameters/OboSignature' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/OboExchangeRequest' }
responses:
'201':
description: Random single-use proof bound to same-organization source, audience, subject token, actor, registered endpoint, method, path, body digest, and exact metadata; valid for at most 60 seconds.
headers:
Cache-Control: { schema: { const: no-store } }
Pragma: { schema: { const: no-cache } }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/OboProofResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/obo-access/verify:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [OBO Access]
operationId: consumeOboAccessProof
description: >-
App B submits the proof and the method, path, and body digest calculated
from the actual downstream request. IAM verifies every binding before
atomically consuming the proof. Successful verification is never stored
or replayed; exactly one concurrent call succeeds and later use returns
409. No Idempotency-Key, X-Org-ID, or actual request body is accepted.
security: [{ applicationBasic: [] }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/OboVerifyRequest' }
responses:
'200':
description: Proof consumed exactly once; returns its bound actor, endpoint, and exact metadata for audience-side authorization.
content:
application/json:
schema: { $ref: '#/components/schemas/OboAccessResult' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'410': { $ref: '#/components/responses/Gone' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/admin/applications:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
get:
tags: [Platform administration]
operationId: adminListApplications
security: [{ platformAdminBearer: [] }]
parameters:
- { $ref: '#/components/parameters/Cursor' }
- { $ref: '#/components/parameters/Limit' }
- { name: status, in: query, schema: { $ref: '#/components/schemas/ApplicationStatus' } }
responses:
'200':
description: Platform review queue and application inventory.
content:
application/json:
schema: { $ref: '#/components/schemas/AdminApplicationPage' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/admin/applications/{app_id}/decisions:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
post:
tags: [Platform administration]
operationId: adminDecideApplication
x-required-step-up-assurance: verified_channel
security: [{ platformAdminBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/AppIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ApplicationAdminDecision' }
responses:
'200':
description: Review, suspension, reactivation, deletion, consent setting, or pending configuration decision applied.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/AdminApplication' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/UnprocessableEntity' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/v1/admin/organizations/{org_id}/sso-entitlement:
parameters:
- { $ref: '#/components/parameters/TestingEnvironmentSelection' }
put:
tags: [Platform administration, SSO]
operationId: adminReplaceSsoEntitlement
x-required-step-up-assurance: verified_channel
security: [{ platformAdminBearer: [], stepUpToken: [] }]
parameters:
- { $ref: '#/components/parameters/OrgIdPath' }
- { $ref: '#/components/parameters/IdempotencyKey' }
- { $ref: '#/components/parameters/IfMatch' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SsoEntitlement' }
responses:
'200':
description: Backend-only SSO entitlement changed.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/SsoEntitlement' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
webhooks:
applicationEvent:
post:
tags: [Webhooks]
operationId: deliverApplicationWebhookEvent
summary: IAM delivers a minimal versioned event to the application's one active HTTPS endpoint.
security: []
parameters:
- { name: X-Silicon-IAM-Event-ID, in: header, required: true, schema: { type: string, format: uuid } }
- { name: X-Silicon-IAM-Timestamp, in: header, required: true, schema: { type: integer } }
- { name: X-Silicon-IAM-Key-Version, in: header, required: true, schema: { type: integer, minimum: 1 } }
- { name: X-Silicon-IAM-Signature, in: header, required: true, schema: { type: string, pattern: '^v1=[a-f0-9]{64}$' } }
requestBody:
required: true
content:
application/json:
schema:
oneOf:
- { $ref: '#/components/schemas/WebhookEvent' }
- { $ref: '#/components/schemas/TestingWebhookEvent' }
responses:
'200': { description: Event accepted idempotently. }
'202': { description: Event accepted for asynchronous local processing. }
'204': { description: Event accepted with no response body. }
siliconEvent:
post:
tags: [Webhooks]
operationId: deliverSiliconWebhookEvent
summary: IAM delivers subscribed organization changes to a Silicon's configured HTTPS endpoint.
security: []
parameters:
- { name: X-Silicon-IAM-Event-ID, in: header, required: true, schema: { type: string, format: uuid } }
- { name: X-Silicon-IAM-Timestamp, in: header, required: true, schema: { type: integer } }
- { name: X-Silicon-IAM-Key-Version, in: header, required: true, schema: { type: integer, minimum: 1 } }
- { name: X-Silicon-IAM-Signature, in: header, required: true, schema: { type: string, pattern: '^v1=[a-f0-9]{64}$' } }
requestBody:
required: true
content:
application/json:
schema:
oneOf:
- { $ref: '#/components/schemas/SiliconWebhookEvent' }
- { $ref: '#/components/schemas/TestingWebhookEvent' }
responses:
'200': { description: Event accepted idempotently. }
'202': { description: Event accepted for asynchronous local processing. }
'204': { description: Event accepted with no response body. }
components:
securitySchemes:
iamBearer:
type: http
scheme: bearer
bearerFormat: opaque IAM access token
description: Carbon, Silicon, or actor-bound application access token; actor class is checked per operation.
sessionCookie:
type: apiKey
in: cookie
name: iam_session
description: Secure, HttpOnly, SameSite browser session used only by interactive authorization flows.
applicationBasic:
type: http
scheme: basic
description: Application ID as username and current versioned application secret as password.
platformAdminBearer:
type: http
scheme: bearer
bearerFormat: opaque platform-admin access token
description: IAM token whose current Carbon principal has active platform-administrator authority.
stepUpToken:
type: apiKey
in: header
name: X-Step-Up-Token
description: Five-minute action-bound token from the step-up verification flow.
testingEnvironmentKey:
type: apiKey
in: header
name: X-Testing-Environment-Key
description: >-
A 32-character alphanumeric testing environment key. Presented on any
other route it selects that environment for the request; presented on
the `/api/v1/testing-environment` routes it is the sole authority.
workosSignature:
type: apiKey
in: header
name: WorkOS-Signature
description: >-
Comma-delimited `t=<epoch_ms>,v1=<hex_hmac>` value. IAM verifies
HMAC-SHA256 over `timestamp + '.' + exact raw UTF-8 body` in constant
time, enforces a 300-second tolerance, and deduplicates provider event ID.
parameters:
TestingEnvironmentSelection:
name: X-Testing-Environment-Key
in: header
required: false
description: >-
Optionally selects an isolated testing data plane for this otherwise
ordinary plane-selected operation. Omit the header to use production. The value
is the 32-character alphanumeric key issued for an active testing
environment; it supplies selection context, not sole authorization.
schema: { $ref: '#/components/schemas/TestingEnvironmentKeyValue' }
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
description: Opaque caller-generated key containing 16 to 255 printable ASCII bytes. Reuse with different bytes returns idempotency_conflict.
schema: { type: string, minLength: 16, maxLength: 255, pattern: '^[\x21-\x7E]{16,255}$' }
OboTimestamp:
name: X-OBO-Timestamp
in: header
required: true
description: Canonical positive Unix timestamp in seconds; accepted only within 60 seconds of IAM's clock.
schema: { type: string, pattern: '^[1-9][0-9]{0,18}$' }
OboSignature:
name: X-OBO-Signature
in: header
required: true
description: >-
Exactly 64 lowercase hexadecimal characters: HMAC-SHA256 using App A's
current Application secret over
timestamp.method.registered_path.body_sha256.Idempotency-Key.
schema: { type: string, pattern: '^[0-9a-f]{64}$' }
IfMatch:
name: If-Match
in: header
required: true
description: Strong ETag containing the expected aggregate version.
schema: { type: string, pattern: '^"[0-9]+"$' }
OrgContext:
name: X-Org-ID
in: header
required: false
description: Optional introspection organization context; it must agree with the token and grant. OBO never accepts this header.
schema: { $ref: '#/components/schemas/OrgId' }
SessionId:
name: session_id
in: path
required: true
schema: { type: string, format: uuid }
CarbonIdPath:
name: carbon_id
in: path
required: true
schema: { $ref: '#/components/schemas/CarbonId' }
OrgIdPath:
name: org_id
in: path
required: true
schema: { $ref: '#/components/schemas/OrgId' }
AppIdPath:
name: app_id
in: path
required: true
schema: { $ref: '#/components/schemas/AppId' }
SiliconIdPath:
name: silicon_id
in: path
required: true
description: Global Silicon handle including the organization suffix.
schema: { $ref: '#/components/schemas/SiliconGlobalId' }
MembershipIdPath:
name: membership_id
in: path
required: true
schema: { type: string, format: uuid }
InviteIdPath:
name: invite_id
in: path
required: true
schema: { type: string, format: uuid }
ApprovalRequestIdPath:
name: request_id
in: path
required: true
schema: { type: string, format: uuid }
TagIdPath:
name: tag_id
in: path
required: true
schema: { type: string, format: uuid }
TrustRuleIdPath:
name: rule_id
in: path
required: true
schema: { type: string, format: uuid }
TestingEnvironmentIdPath:
name: environment_id
in: path
required: true
schema: { type: string, format: uuid }
TestingEnvironmentStatus:
name: status
in: query
required: false
description: Lifecycle filter. Defaults to `active`; `all` includes environments awaiting purge.
schema: { type: string, enum: [active, deleted, all], default: active }
TestingEnvironmentCursor:
name: cursor
in: query
required: false
description: Identifier of the last environment on the previous page.
schema: { type: string, format: uuid }
TestingEnvironmentLimit:
name: limit
in: query
required: false
schema: { type: integer, minimum: 1, maximum: 100, default: 25 }
Cursor:
name: cursor
in: query
required: false
description: Opaque continuation cursor scoped to the filters and caller.
schema: { type: string, minLength: 1, maxLength: 2048 }
Limit:
name: limit
in: query
required: false
schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
DirectoryFields:
name: fields
in: query
required: false
description: Comma-separated sparse projection. Omit it to return every directory field.
schema:
type: string
minLength: 1
pattern: '^(name|id|role|org|tags|trust)(,(name|id|role|org|tags|trust))*$'
headers:
RequestId:
description: Trace identifier generated or accepted from X-Request-ID.
schema: { type: string, minLength: 1, maxLength: 128 }
ETag:
description: Strong aggregate-version ETag.
schema: { type: string, pattern: '^"[0-9]+"$' }
RetryAfter:
description: Seconds before retrying.
schema: { type: integer, minimum: 1 }
RateLimitLimit:
description: Effective request limit for the tightest active bucket.
schema: { type: integer, minimum: 1 }
RateLimitRemaining:
description: Remaining requests in that bucket.
schema: { type: integer, minimum: 0 }
RateLimitReset:
description: Seconds until that bucket resets.
schema: { type: integer, minimum: 0 }
IdempotencyReplayed:
description: True when this is a replay of the stored idempotent response.
schema: { type: boolean }
requestBodies:
VerificationCode:
required: true
content:
application/json:
schema:
type: object
required: [code]
additionalProperties: false
properties:
code: { $ref: '#/components/schemas/VerificationCode' }
responses:
HealthOk:
description: Process is healthy for the requested probe.
content:
application/json:
schema:
type: object
required: [ok]
properties: { ok: { const: true } }
CodeDispatchAccepted:
description: >-
Signup contact check completed. If the normalized identity already
belongs to a Carbon, no OTP is sent and already_exists is true.
Otherwise a ten-minute OTP is dispatched and already_exists is false.
headers:
X-Request-ID: { $ref: '#/components/headers/RequestId' }
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema: { $ref: '#/components/schemas/CodeDispatchResult' }
Verified:
description: Verification completed and the OTP was consumed atomically.
headers:
Idempotency-Replayed: { $ref: '#/components/headers/IdempotencyReplayed' }
content:
application/json:
schema:
type: object
required: [verified]
properties: { verified: { const: true } }
BadRequest:
description: Malformed syntax, unsupported media type, or invalid protocol request.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
Unauthorized:
description: Missing, invalid, expired, or revoked authentication.
headers: { WWW-Authenticate: { schema: { type: string } } }
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
Forbidden:
description: Authenticated principal lacks the current actor type, scope, capability, or step-up authorization.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
NotFound:
description: Resource is absent or intentionally hidden across a tenant boundary.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
Conflict:
description: Unique, idempotency, replay, terminal-state, or concurrent-state conflict.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
NotAcceptable:
description: The client and server do not support a common public API version.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
Gone:
description: One-time challenge, short-lived login token, invitation, proof, or response window expired.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
PreconditionFailed:
description: If-Match does not equal the current aggregate version.
headers: { ETag: { $ref: '#/components/headers/ETag' } }
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
PayloadTooLarge:
description: Request body exceeds the endpoint's configured bound.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
UnprocessableEntity:
description: Well-formed request violates field, policy, hierarchy, quorum, or tenant invariants.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
PreconditionRequired:
description: Required Idempotency-Key, If-Match, or step-up precondition is absent.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
TooManyRequests:
description: One or more distributed request buckets are exhausted, or an OTP challenge is inside its 60-second cooldown after ten failed verifications.
headers:
Retry-After: { $ref: '#/components/headers/RetryAfter' }
RateLimit-Limit: { $ref: '#/components/headers/RateLimitLimit' }
RateLimit-Remaining: { $ref: '#/components/headers/RateLimitRemaining' }
RateLimit-Reset: { $ref: '#/components/headers/RateLimitReset' }
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
BadGateway:
description: Authenticated upstream provider returned an invalid or failed response.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
ServiceUnavailable:
description: Required local dependency or provider is temporarily unavailable.
headers: { Retry-After: { $ref: '#/components/headers/RetryAfter' } }
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
GatewayTimeout:
description: A bounded server or provider processing deadline elapsed.
content: { application/json: { schema: { $ref: '#/components/schemas/ErrorEnvelope' } } }
schemas:
ErrorEnvelope:
type: object
required: [error]
additionalProperties: false
properties:
error:
type: object
required: [code, message, request_id]
additionalProperties: false
properties:
code: { type: string, pattern: '^[a-z][a-z0-9_]{1,63}$' }
message: { type: string, minLength: 1, maxLength: 500 }
details: { type: object, additionalProperties: true }
request_id: { type: string, minLength: 1, maxLength: 128 }
VersionInfo:
type: object
required: [service, api_version, build, commit]
properties:
service: { const: silicon-iam }
api_version: { const: v1 }
build: { type: string }
commit: { type: string }
ApiVersionNegotiation:
type: object
required: [service, selected_api_version, supported_api_versions, build, commit]
additionalProperties: false
properties:
service: { const: silicon-iam }
selected_api_version: { type: string, pattern: '^v[1-9][0-9]{0,8}$' }
supported_api_versions:
type: array
minItems: 1
maxItems: 16
uniqueItems: true
description: Server-supported API majors in descending preference order.
items: { type: string, pattern: '^v[1-9][0-9]{0,8}$' }
build: { type: string }
commit: { type: string }
VerificationCode:
type: string
pattern: '^[0-9]{6}$'
description: Six-digit code with a ten-minute expiry; ten failed verifications trigger a 60-second reusable-challenge cooldown.
CarbonId:
type: string
pattern: '^[a-z1-9_-]{3,30}$'
description: New immutable Carbon ID; zero is not admitted.
ExistingCarbonId:
type: string
pattern: '^[a-z0-9_-]{3,30}$'
description: Existing Carbon lookup/projection, including immutable legacy IDs containing zero.
OrgId: { type: string, pattern: '^[a-z0-9_-]{3,50}$' }
ApplicationHandle:
type: string
pattern: '^[a-z][a-z0-9_-]{2,79}$'
description: Local handle supplied at creation; the public id becomes `{org_id}>{handle}`.
AppId:
type: string
pattern: '^[a-z0-9_-]{3,50}>[a-z][a-z0-9_-]{2,79}$'
description: Canonical organization-qualified Application id, `{org_id}>{handle}`.
SiliconHandle:
type: string
pattern: '^[a-z0-9_-]{3,50}$'
description: Client-supplied handle component; only the resulting `{handle}:{org_id}` Silicon ID is public.
SiliconGlobalId: { type: string, pattern: '^[a-z0-9_-]{3,50}:[a-z0-9_-]{3,50}$' }
TimeZoneId:
type: string
minLength: 1
maxLength: 255
pattern: '^[A-Za-z0-9._+-]+(/[A-Za-z0-9._+-]+)*$'
description: Exact identifier that must resolve in the IANA Time Zone Database, such as UTC or Asia/Kolkata.
EmailInput:
type: object
required: [email]
additionalProperties: false
properties: { email: { type: string, format: email, maxLength: 320 } }
PhoneInput:
type: object
required: [phone_number]
additionalProperties: false
properties: { phone_number: { type: string, pattern: '^\\+[1-9][0-9]{7,14}$' } }
AuthSession:
type: object
required: [session_id, expires_at]
additionalProperties: false
properties:
session_id: { type: string, format: uuid }
expires_at: { type: string, format: date-time }
local_otp:
type: string
pattern: '^[0-9]{6}$'
description: Present only when the explicitly configured local-development provider exposes the generated code.
CodeDispatchResult:
type: object
required: [already_exists]
additionalProperties: false
properties:
already_exists: { type: boolean }
expires_in:
type: integer
const: 600
description: Present only when a new verification code was sent.
local_otp:
type: string
pattern: '^[0-9]{6}$'
description: Present only when the explicitly configured local-development provider exposes the generated code.
Availability:
type: object
required: [available]
properties: { available: { type: boolean } }
ActorRef:
type: object
required: [principal_id, type, public_id]
additionalProperties: false
properties:
principal_id: { type: string, format: uuid }
type: { type: string, enum: [carbon, silicon, application] }
public_id: { type: string }
CarbonPublic:
type: object
required: [principal_id, carbon_id, display_name, profile_photo, created_at]
properties:
principal_id: { type: string, format: uuid }
carbon_id: { $ref: '#/components/schemas/ExistingCarbonId' }
display_name: { type: string, minLength: 1, maxLength: 200 }
description: { type: [string, 'null'], maxLength: 5000 }
profile_photo: { type: string, format: uri, maxLength: 2048 }
created_at: { type: string, format: date-time }
CarbonSuggestion:
type: object
required: [carbon_id]
additionalProperties: false
properties:
carbon_id: { $ref: '#/components/schemas/ExistingCarbonId' }
CarbonResolution:
type: object
required: [carbon_id]
additionalProperties: false
properties:
carbon_id: { $ref: '#/components/schemas/ExistingCarbonId' }
CarbonSelf:
allOf:
- { $ref: '#/components/schemas/CarbonPublic' }
- type: object
required: [timezone, email, phone_number, status, version, updated_at]
properties:
timezone: { $ref: '#/components/schemas/TimeZoneId' }
email: { type: string, format: email }
phone_number: { type: string }
status: { type: string, enum: [active, suspended] }
version: { type: integer, minimum: 1 }
updated_at: { type: string, format: date-time }
CarbonSignupComplete:
type: object
required: [carbon_id, display_name]
additionalProperties: false
properties:
carbon_id: { $ref: '#/components/schemas/CarbonId' }
display_name: { type: string, minLength: 1, maxLength: 200 }
timezone:
allOf: [{ $ref: '#/components/schemas/TimeZoneId' }]
description: Defaults to UTC when omitted.
description: { type: [string, 'null'], maxLength: 5000 }
profile_photo: { type: [string, 'null'], format: uri, maxLength: 2048 }
CarbonProfilePatch:
type: object
minProperties: 1
additionalProperties: false
properties:
display_name: { type: string, minLength: 1, maxLength: 200 }
timezone: { $ref: '#/components/schemas/TimeZoneId' }
description: { type: [string, 'null'], maxLength: 5000 }
profile_photo: { type: [string, 'null'], format: uri, maxLength: 2048 }
LoginChallengeCreate:
type: object
minProperties: 1
maxProperties: 1
oneOf:
- { required: [email] }
- { required: [phone_number] }
- { required: [carbon_id] }
additionalProperties: false
properties:
email: { type: string, format: email, maxLength: 320 }
phone_number: { type: string, pattern: '^\\+[1-9][0-9]{7,14}$' }
carbon_id: { $ref: '#/components/schemas/ExistingCarbonId' }
StepUpAction:
type: string
description: >-
Closed privileged-action catalog. account.session_revoke binds
resource_id to the target session UUID; account.sessions_revoke_all
binds it to the current Carbon principal UUID. The Silicon-webhook
redirect action binds it to the target Silicon membership UUID. The
Application client-secret rotation action binds it to the internal
Application UUID. Every action requires one non-null resource_id.
enum:
- account.session_revoke
- account.sessions_revoke_all
- organization.transfer_ownership
- organization.authorization_change
- organization.sso_change
- organization.silicon_webhook.redirect
- application.client_secret.rotate
- application.webhook_secret.rotate
- silicon.rotate_token
- platform_admin.sso_entitlement
- platform_admin.application_review
StepUpChallengeCreate:
type: object
required: [channel, action, resource_id]
additionalProperties: false
properties:
channel: { type: string, enum: [email, phone_number] }
action: { $ref: '#/components/schemas/StepUpAction' }
resource_id: { type: string, format: uuid }
StepUpTokenResponse:
type: object
required: [step_up_token, action, assurance, expires_in]
properties:
step_up_token: { type: string, pattern: '^sup_[A-Za-z0-9_-]{43}$' }
action: { $ref: '#/components/schemas/StepUpAction' }
assurance: { type: string, enum: [verified_channel] }
expires_in: { type: integer, const: 300 }
IamTokenResponse:
type: object
required: [access_token, refresh_token, token_type, expires_in, refresh_expires_at, actor, session_id]
properties:
access_token:
type: string
pattern: '^(cat|sat)_[A-Za-z0-9_-]{43}$'
description: Carbon access tokens use cat_; Silicon access tokens use sat_.
refresh_token: { type: string, pattern: '^rft_[A-Za-z0-9_-]{43}$' }
token_type: { const: Bearer }
expires_in: { type: integer, const: 1800 }
refresh_expires_at: { type: string, format: date-time, description: Exactly 900 days from family creation. }
actor: { $ref: '#/components/schemas/ActorRef' }
session_id: { type: string, format: uuid }
RefreshTokenRequest:
type: object
required: [refresh_token]
additionalProperties: false
properties:
refresh_token: { type: string, minLength: 32, maxLength: 512 }
TokenIntrospectionRequest:
type: object
required: [token]
properties:
token: { type: string, minLength: 32, maxLength: 4096 }
token_type_hint: { type: string, enum: [access_token, refresh_token] }
TokenIntrospection:
type: object
description: >-
Live token state. An active organization-bound access token also returns
authorization, a synchronous bootstrap/resynchronization snapshot. No
directory mutation or webhook delivery is required. Refresh tokens and
unscoped access tokens do not carry organization authorization.
required: [active]
properties:
active: { type: boolean }
principal_id: { type: string, format: uuid }
actor_type: { type: string, enum: [carbon, silicon, application] }
client_id: { $ref: '#/components/schemas/AppId' }
org_id: { $ref: '#/components/schemas/OrgId' }
membership_id: { type: string, format: uuid }
session_id: { type: string, format: uuid }
scope: { type: string }
audience: { type: string }
issued_at: { type: integer }
expires_at: { type: integer }
authorization_epoch: { type: integer, minimum: 0 }
authorization: { $ref: '#/components/schemas/ApplicationAuthorization' }
AuthorizationTag:
type: object
required: [id, name]
properties:
id: { type: string, format: uuid }
name: { type: string }
ApplicationAuthorization:
type: object
description: >-
Current active membership bound to the authenticated token or verified
proof, audience, organization, principal and testing plane. Use on first
login and cache misses; webhook snapshots are asynchronous updates, not
prerequisites for initial access. org_role requires roles.read and tags
requires memberships.read. Null means undisclosed, not member or empty
tags. OBO disclosure uses the intersection of the parent token scopes
and recipient application's currently approved scopes. The binding
authorizes no action outside the verified proof's endpoint/request.
Do not reuse it for a different principal, membership, epoch, audience,
organization, environment or effective scope set. Never fill undisclosed
fields from a broader cached token. Introspect current bearer tokens again
before relying on cached authority; a consumed OBO proof is single-use.
required: [principal_id, actor_type, public_id, organization_id, org_id, membership_id, membership_version, authorization_epoch, audience, testing_environment_id, scopes, org_role, tags]
properties:
principal_id: { type: string, format: uuid }
actor_type: { type: string, enum: [carbon, silicon] }
public_id: { type: string }
organization_id: { type: string, format: uuid }
org_id: { $ref: '#/components/schemas/OrgId' }
membership_id: { type: string, format: uuid }
membership_version: { type: integer, minimum: 1 }
authorization_epoch: { type: integer, minimum: 0 }
audience: { $ref: '#/components/schemas/AppId' }
testing_environment_id: { type: [string, 'null'], format: uuid }
scopes: { type: array, items: { type: string } }
org_role: { type: [string, 'null'], enum: [owner, admin, member, null] }
tags: { type: [array, 'null'], items: { $ref: '#/components/schemas/AuthorizationTag' } }
LogoutRequest:
type: object
additionalProperties: false
properties:
mode: { type: string, enum: [current_session, all_sessions], default: current_session }
Session:
type: object
required: [session_id, actor, status, created_at, last_used_at, absolute_expires_at]
properties:
session_id: { type: string, format: uuid }
actor: { $ref: '#/components/schemas/ActorRef' }
status: { type: string, enum: [active, revoked, expired, replay_revoked] }
user_agent_summary: { type: [string, 'null'], maxLength: 500 }
ip_prefix: { type: [string, 'null'], maxLength: 64 }
created_at: { type: string, format: date-time }
last_used_at: { type: string, format: date-time }
absolute_expires_at: { type: string, format: date-time }
revoked_at: { type: [string, 'null'], format: date-time }
PageInfo:
type: object
required: [next_cursor, has_more]
properties:
next_cursor: { type: [string, 'null'] }
has_more: { type: boolean }
SessionPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/Session' } }
page: { $ref: '#/components/schemas/PageInfo' }
LoginEvent:
type: object
required: [id, actor, event_type, occurred_at, success, request_id]
properties:
id: { type: string, format: uuid }
actor: { $ref: '#/components/schemas/ActorRef' }
app_id: { type: [string, 'null'] }
org_id: { type: [string, 'null'] }
event_type: { type: string, enum: [login_challenge, login_success, login_failure, oauth_authorization, oauth_token_exchange, logout, refresh_replay] }
success: { type: boolean }
ip_prefix: { type: [string, 'null'] }
user_agent_summary: { type: [string, 'null'] }
request_id: { type: string }
occurred_at: { type: string, format: date-time }
LoginEventPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/LoginEvent' } }
page: { $ref: '#/components/schemas/PageInfo' }
SiliconAuthenticationRequest:
type: object
required: [silicon_id, silicon_token]
additionalProperties: false
properties:
silicon_id: { $ref: '#/components/schemas/SiliconGlobalId' }
silicon_token: { type: string, pattern: '^stk-[a-f0-9]{32}$' }
ShortLivedTokenRequest:
type: object
required: [app_id]
additionalProperties: false
properties:
app_id: { $ref: '#/components/schemas/AppId' }
org_id:
allOf: [{ $ref: '#/components/schemas/OrgId' }]
description: Optional organization membership to bind into the resulting Application tokens. Omit for an unscoped login.
ShortLivedToken:
type: object
required: [slt, expires_in]
properties:
slt: { type: string }
expires_in: { type: integer }
ApplicationTokenRequest:
type: object
required: [app_id]
additionalProperties: false
oneOf:
- required: [slt]
- required: [refresh_token]
properties:
app_id: { $ref: '#/components/schemas/AppId' }
slt: { type: string, minLength: 32, maxLength: 512 }
refresh_token: { type: string, minLength: 32, maxLength: 512 }
OAuthTokenResponse:
type: object
required: [access_token, refresh_token, token_type, expires_in, scope, actor]
properties:
access_token: { type: string, pattern: '^oat_[A-Za-z0-9_-]{43}$' }
refresh_token: { type: string, pattern: '^ort_[A-Za-z0-9_-]{43}$' }
token_type: { const: Bearer }
expires_in: { type: integer, const: 1800 }
scope: { type: string }
actor: { $ref: '#/components/schemas/ActorRef' }
org_id: { type: [string, 'null'] }
OAuthRevocationRequest:
type: object
required: [token]
properties:
token: { type: string, minLength: 32, maxLength: 4096 }
token_type_hint: { type: string, enum: [access_token, refresh_token] }
OrganizationCreate:
type: object
required: [org_id, name]
additionalProperties: false
properties:
org_id: { $ref: '#/components/schemas/OrgId' }
name: { type: string, minLength: 1, maxLength: 200 }
logo: { type: [string, 'null'], format: uri, maxLength: 2048 }
description: { type: [string, 'null'], maxLength: 5000 }
OrganizationPatch:
type: object
minProperties: 1
additionalProperties: false
properties:
name: { type: string, minLength: 1, maxLength: 200 }
logo: { type: [string, 'null'], format: uri, maxLength: 2048 }
description: { type: [string, 'null'], maxLength: 5000 }
join_method: { type: string, enum: [email, sso] }
Organization:
type: object
required: [id, org_id, name, owner_membership_id, join_method, sso_status, status, version, created_at, updated_at]
properties:
id: { type: string, format: uuid }
org_id: { $ref: '#/components/schemas/OrgId' }
name: { type: string }
logo: { type: [string, 'null'], format: uri }
description: { type: [string, 'null'] }
owner_membership_id: { type: string, format: uuid }
join_method: { type: string, enum: [email, sso] }
sso_status: { type: string, enum: [disabled, pending, active, error] }
status: { type: string, enum: [active, disabled] }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
OrganizationPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/Organization' } }
page: { $ref: '#/components/schemas/PageInfo' }
OwnershipTransfer:
type: object
required: [new_owner_membership_id]
additionalProperties: false
properties:
new_owner_membership_id: { type: string, format: uuid }
OrganizationCapability:
type: string
enum:
- organization.update
- members.invite
- members.update_directory
- members.remove
- silicons.create
- silicons.update_directory
- silicons.manage_hierarchy
- silicons.remove
- silicons.rotate_token
- tags.manage
- trust.manage
- roles.request
- roles.approve
- admins.create
- admins.manage
- sso.manage
Membership:
type: object
required: [id, org_id, principal, status, org_role, job_role, tags, extra_silicons, authorization_epoch, version, created_at, updated_at]
properties:
id: { type: string, format: uuid }
org_id: { $ref: '#/components/schemas/OrgId' }
principal: { $ref: '#/components/schemas/ActorRef' }
status: { type: string, enum: [active, removed] }
org_role: { type: string, enum: [owner, admin, member] }
job_role: { type: string, maxLength: 5000 }
tags: { type: array, uniqueItems: true, items: { $ref: '#/components/schemas/TagSummary' } }
first_silicon_membership_id: { type: [string, 'null'], format: uuid }
extra_silicons: { type: array, uniqueItems: true, items: { type: string, format: uuid } }
default_trust:
description: Carbon-wide advisory trust baseline; null for Silicon memberships.
oneOf:
- { $ref: '#/components/schemas/TrustValue' }
- { type: 'null' }
reports_to_membership_id: { type: [string, 'null'], format: uuid }
hierarchy_level: { type: [integer, 'null'], minimum: 1 }
authorization_epoch: { type: integer, minimum: 0 }
removed_at: { type: [string, 'null'], format: date-time }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
MembershipPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/Membership' } }
page: { $ref: '#/components/schemas/PageInfo' }
MembershipDirectoryPatch:
type: object
minProperties: 1
additionalProperties: false
properties:
first_silicon_membership_id: { type: [string, 'null'], format: uuid }
extra_silicon_membership_ids: { type: array, uniqueItems: true, maxItems: 500, items: { type: string, format: uuid } }
default_trust:
allOf: [{ $ref: '#/components/schemas/TrustValue' }]
description: Carbon-only advisory trust baseline; requires trust.manage.
reports_to_membership_id: { type: [string, 'null'], format: uuid }
profile_photo: { type: [string, 'null'], format: uri, maxLength: 2048 }
MembershipAuthorization:
type: object
required: [membership_id, org_role, capabilities, authorization_epoch, version]
properties:
membership_id: { type: string, format: uuid }
org_role: { type: string, enum: [owner, admin, member] }
capabilities: { type: array, uniqueItems: true, items: { $ref: '#/components/schemas/OrganizationCapability' } }
authorization_epoch: { type: integer, minimum: 0 }
version: { type: integer, minimum: 1 }
OrganizationCapabilitiesReplace:
type: object
required: [capabilities]
additionalProperties: false
properties:
capabilities: { type: array, uniqueItems: true, items: { $ref: '#/components/schemas/OrganizationCapability' } }
DirectoryRole:
type: object
required: [org_role, job_role]
additionalProperties: false
properties:
org_role: { type: string, enum: [owner, admin, member] }
job_role: { type: string, maxLength: 5000 }
DirectoryOrganization:
type: object
required: [id, name]
additionalProperties: false
properties:
id: { $ref: '#/components/schemas/OrgId' }
name: { type: string, minLength: 1, maxLength: 200 }
DirectoryMember:
type: object
additionalProperties: false
description: >-
Sparse organization-directory projection. Omitted fields were not
requested. trust is null when no Carbon-to-Silicon or
Silicon-to-Carbon/Silicon orientation exists, including Carbon-to-Carbon.
properties:
name: { type: string, minLength: 1, maxLength: 200 }
id:
type: string
description: Public Carbon ID or global Silicon ID.
role: { $ref: '#/components/schemas/DirectoryRole' }
org: { $ref: '#/components/schemas/DirectoryOrganization' }
tags: { type: array, uniqueItems: true, items: { $ref: '#/components/schemas/TagSummary' } }
trust:
oneOf:
- { $ref: '#/components/schemas/TrustEvaluation' }
- { type: 'null' }
DirectoryPage:
type: object
required: [items, page]
additionalProperties: false
properties:
items: { type: array, items: { $ref: '#/components/schemas/DirectoryMember' } }
page: { $ref: '#/components/schemas/PageInfo' }
TrustValue:
type: object
required: [boundary, level]
additionalProperties: false
properties:
boundary: { type: string, enum: [internal, external] }
level: { type: string, enum: [not_trusted, needs_approval, trusted] }
InvitationTagTrustOverride:
type: object
required: [tag_id, trust]
additionalProperties: false
properties:
tag_id: { type: string, format: uuid }
trust: { $ref: '#/components/schemas/TrustValue' }
InvitationSiliconTrustOverride:
type: object
required: [silicon_membership_id, trust]
additionalProperties: false
properties:
silicon_membership_id: { type: string, format: uuid }
trust: { $ref: '#/components/schemas/TrustValue' }
CarbonInviteCreate:
type: object
required: [job_role, default_trust]
minProperties: 3
oneOf:
- { required: [carbon_id] }
- { required: [email] }
additionalProperties: false
properties:
carbon_id: { $ref: '#/components/schemas/ExistingCarbonId' }
email: { type: string, format: email, maxLength: 320 }
job_role: { type: string, maxLength: 5000 }
tag_ids: { type: array, uniqueItems: true, maxItems: 100, items: { type: string, format: uuid } }
first_silicon_membership_id: { type: [string, 'null'], format: uuid }
extra_silicon_membership_ids: { type: array, uniqueItems: true, maxItems: 500, items: { type: string, format: uuid } }
default_trust: { $ref: '#/components/schemas/TrustValue' }
tag_trust_overrides:
type: array
maxItems: 100
default: []
description: At most one override per active organization tag.
items: { $ref: '#/components/schemas/InvitationTagTrustOverride' }
silicon_trust_overrides:
type: array
maxItems: 500
default: []
description: At most one override per active Silicon membership.
items: { $ref: '#/components/schemas/InvitationSiliconTrustOverride' }
redirect_app_id:
type: [string, 'null']
pattern: '^[a-z0-9_-]{3,50}>[a-z][a-z0-9_-]{2,79}$'
description: Canonical organization-qualified Application id when the invitation should continue into an Application login.
InviteStatus: { type: string, enum: [pending, accepted, revoked, expired] }
Invite:
type: object
required: [id, org_id, target_carbon, org_role, job_role, tag_ids, extra_silicon_membership_ids, default_trust, tag_trust_overrides, silicon_trust_overrides, invited_by, status, expires_at, version, created_at]
properties:
id: { type: string, format: uuid }
org_id: { $ref: '#/components/schemas/OrgId' }
target_carbon: { $ref: '#/components/schemas/CarbonPublic' }
masked_delivery_address: { type: string }
org_role: { const: member }
job_role: { type: string, maxLength: 5000 }
tag_ids: { type: array, uniqueItems: true, items: { type: string, format: uuid } }
first_silicon_membership_id: { type: [string, 'null'], format: uuid }
extra_silicon_membership_ids: { type: array, uniqueItems: true, items: { type: string, format: uuid } }
default_trust: { $ref: '#/components/schemas/TrustValue' }
tag_trust_overrides:
type: array
items: { $ref: '#/components/schemas/InvitationTagTrustOverride' }
silicon_trust_overrides:
type: array
items: { $ref: '#/components/schemas/InvitationSiliconTrustOverride' }
invited_by: { $ref: '#/components/schemas/ActorRef' }
status: { $ref: '#/components/schemas/InviteStatus' }
expires_at: { type: string, format: date-time }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
accepted_at: { type: [string, 'null'], format: date-time }
InvitePage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/Invite' } }
page: { $ref: '#/components/schemas/PageInfo' }
InvitationAcceptance:
type: object
required: [invite_id, verification_code]
additionalProperties: false
properties:
invite_id: { type: string, format: uuid }
verification_code: { $ref: '#/components/schemas/VerificationCode' }
InvitationEmailCodeResponse:
type: object
required: [accepted, invite_id, expires_in]
additionalProperties: false
properties:
accepted: { const: true }
invite_id: { type: string, format: uuid }
expires_in: { type: integer, minimum: 1, maximum: 600 }
SiliconCreate:
type: object
required: [silicon_id, job_role]
additionalProperties: false
properties:
silicon_id: { $ref: '#/components/schemas/SiliconHandle' }
display_name:
type: string
minLength: 1
maxLength: 200
description: Defaults to the immutable local Silicon handle when omitted.
timezone:
allOf: [{ $ref: '#/components/schemas/TimeZoneId' }]
description: Defaults to UTC when omitted.
description: { type: [string, 'null'], maxLength: 5000 }
profile_photo: { type: [string, 'null'], format: uri, maxLength: 2048 }
job_role: { type: string, maxLength: 5000 }
reports_to_membership_id: { type: [string, 'null'], format: uuid }
tag_ids: { type: array, uniqueItems: true, maxItems: 100, items: { type: string, format: uuid } }
SiliconPatch:
type: object
minProperties: 1
additionalProperties: false
properties:
display_name: { type: string, minLength: 1, maxLength: 200 }
timezone: { $ref: '#/components/schemas/TimeZoneId' }
description: { type: [string, 'null'], maxLength: 5000 }
profile_photo: { type: [string, 'null'], format: uri, maxLength: 2048 }
reports_to_membership_id: { type: [string, 'null'], format: uuid }
Silicon:
type: object
required: [principal_id, membership_id, silicon_id, org_id, display_name, timezone, profile_photo, job_role, tags, hierarchy_level, webhook_configured, status, version, created_at, updated_at]
properties:
principal_id: { type: string, format: uuid }
membership_id: { type: string, format: uuid }
silicon_id: { $ref: '#/components/schemas/SiliconGlobalId' }
org_id: { $ref: '#/components/schemas/OrgId' }
display_name: { type: string, minLength: 1, maxLength: 200 }
timezone: { $ref: '#/components/schemas/TimeZoneId' }
description: { type: [string, 'null'], maxLength: 5000 }
profile_photo: { type: string, format: uri }
job_role: { type: string, maxLength: 5000 }
reports_to_membership_id: { type: [string, 'null'], format: uuid }
tags: { type: array, items: { $ref: '#/components/schemas/TagSummary' } }
hierarchy_level: { type: integer, minimum: 1 }
webhook_configured: { type: boolean }
status: { type: string, enum: [active, removed] }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
SiliconCreated:
type: object
required: [silicon, silicon_token, secret_replay_expires_at]
properties:
silicon: { $ref: '#/components/schemas/Silicon' }
silicon_token: { type: string, pattern: '^stk-[a-f0-9]{32}$' }
secret_replay_expires_at: { type: string, format: date-time }
SiliconPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/Silicon' } }
page: { $ref: '#/components/schemas/PageInfo' }
SiliconWebhookReplace:
type: object
required: [url]
additionalProperties: false
properties:
url: { type: string, format: uri, pattern: '^https://', maxLength: 2048 }
SiliconWebhook:
type: object
required: [silicon_id, url, status, secret_version, version, created_at, updated_at]
properties:
silicon_id: { $ref: '#/components/schemas/SiliconGlobalId' }
url: { type: string, format: uri, pattern: '^https://', maxLength: 2048 }
status: { const: active }
secret_version: { type: integer, minimum: 1 }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
SiliconWebhookConfigured:
type: object
required: [webhook, webhook_signing_secret, secret_replay_expires_at]
properties:
webhook: { $ref: '#/components/schemas/SiliconWebhook' }
webhook_signing_secret: { type: string, pattern: '^swhs_[A-Za-z0-9_-]{43}$' }
secret_replay_expires_at: { type: string, format: date-time }
SiliconWebhookSubscriptionTopic:
type: string
enum: [membership_lifecycle, member_updates, trust_updates]
SiliconWebhookSubscriptionReplace:
type: object
required: [mode]
additionalProperties: false
description: >-
all receives every explicitly Silicon-routed organization event, including
Full-only metadata, catalog, invitation, governance, credential, and
configuration events, and canonicalizes the response to all three topic
values. selected requires at least one exact topic: membership_lifecycle is
actual creation/reactivation/removal, member_updates is applied existing-member
role/tag/profile/hierarchy/authorization/ownership change, and trust_updates is
trust state only. Optional tag_filter always includes the Silicon's own
event-time before/after tag audience and may add active organization tags;
later own-tag changes never alter an older event's audience.
properties:
mode: { type: string, enum: [all, selected] }
topics:
type: array
uniqueItems: true
maxItems: 3
default: []
items: { $ref: '#/components/schemas/SiliconWebhookSubscriptionTopic' }
tag_filter:
oneOf:
- { $ref: '#/components/schemas/SiliconWebhookTagFilter' }
- { type: 'null' }
SiliconWebhookTagFilter:
type: object
additionalProperties: false
properties:
additional_tag_ids:
type: array
uniqueItems: true
maxItems: 100
default: []
items: { type: string, format: uuid }
SiliconWebhookSubscription:
type: object
required: [silicon_id, mode, topics, tag_filter, version, created_at, updated_at]
properties:
silicon_id: { $ref: '#/components/schemas/SiliconGlobalId' }
mode: { type: string, enum: [all, selected] }
topics:
type: array
minItems: 1
maxItems: 3
uniqueItems: true
items: { $ref: '#/components/schemas/SiliconWebhookSubscriptionTopic' }
tag_filter:
description: >-
Null disables tag filtering. When present, organization-wide and
unattributed events are suppressed; affected tags must intersect
either the Silicon's immutable event-time own-tag audience or a
currently configured additional tag.
oneOf:
- { $ref: '#/components/schemas/SiliconWebhookTagFilter' }
- { type: 'null' }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
SiliconTokenRotated:
type: object
required: [silicon_id, credential_version, silicon_token, secret_replay_expires_at]
properties:
silicon_id: { $ref: '#/components/schemas/SiliconGlobalId' }
credential_version: { type: integer, minimum: 1 }
silicon_token: { type: string, pattern: '^stk-[a-f0-9]{32}$' }
secret_replay_expires_at: { type: string, format: date-time }
TagCreate:
type: object
required: [name]
additionalProperties: false
properties: { name: { type: string, minLength: 1, maxLength: 100 } }
TagPatch:
type: object
required: [name]
additionalProperties: false
properties: { name: { type: string, minLength: 1, maxLength: 100 } }
TagSummary:
type: object
required: [id, name]
properties:
id: { type: string, format: uuid }
name: { type: string }
Tag:
allOf:
- { $ref: '#/components/schemas/TagSummary' }
- type: object
required: [org_id, version, created_at, updated_at]
properties:
org_id: { $ref: '#/components/schemas/OrgId' }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
TagPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/Tag' } }
page: { $ref: '#/components/schemas/PageInfo' }
TestingEnvironment:
type: object
required:
[id, org_id, name, description, status, created_by_membership_id,
key_generation, key_rotated_at, last_activity_at, cleaned_at,
deleted_at, purge_after, version, created_at, updated_at]
properties:
id: { type: string, format: uuid }
org_id: { $ref: '#/components/schemas/OrgId' }
name: { type: string, minLength: 1, maxLength: 64 }
description: { type: [string, 'null'], maxLength: 500 }
status: { type: string, enum: [active, deleted] }
created_by_membership_id:
type: string
format: uuid
description: Membership that created the environment; it keeps administrative authority while active.
key_generation:
type: integer
minimum: 1
description: Increments on every key rotation.
key_rotated_at: { type: [string, 'null'], format: date-time }
last_activity_at:
type: string
format: date-time
description: Last accepted request in the environment; idleness beyond the configured window auto-deletes it.
cleaned_at: { type: [string, 'null'], format: date-time }
deleted_at: { type: [string, 'null'], format: date-time }
purge_after:
type: [string, 'null']
format: date-time
description: Deadline after which the environment and its data are destroyed permanently. Restorable until then.
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
TestingEnvironmentPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/TestingEnvironment' } }
page:
type: object
required: [next_cursor, has_more]
properties:
next_cursor: { type: [string, 'null'], format: uuid }
has_more: { type: boolean }
TestingEnvironmentCreate:
type: object
additionalProperties: false
required: [name]
properties:
name: { type: string, minLength: 1, maxLength: 64 }
description: { type: [string, 'null'], maxLength: 500 }
TestingEnvironmentPatch:
type: object
additionalProperties: false
minProperties: 1
properties:
name: { type: string, minLength: 1, maxLength: 64 }
description: { type: [string, 'null'], maxLength: 500 }
TestingEnvironmentKeyValue:
type: string
pattern: '^[A-Za-z0-9]{32}$'
description: Root authority for one environment. Anyone holding it can do anything inside that environment.
TestingEnvironmentWithKey:
allOf:
- { $ref: '#/components/schemas/TestingEnvironment' }
- type: object
required: [key]
properties:
key: { $ref: '#/components/schemas/TestingEnvironmentKeyValue' }
TestingEnvironmentKey:
type: object
required: [environment_id, key_generation, key_rotated_at, key]
properties:
environment_id: { type: string, format: uuid }
key_generation: { type: integer, minimum: 1 }
key_rotated_at: { type: [string, 'null'], format: date-time }
key: { $ref: '#/components/schemas/TestingEnvironmentKeyValue' }
TestingEnvironmentSelf:
type: object
required: [id, name, description, key_generation, created_at]
description: What a key holder may see about the environment it holds a key to.
properties:
id: { type: string, format: uuid }
name: { type: string, minLength: 1, maxLength: 64 }
description: { type: [string, 'null'], maxLength: 500 }
key_generation: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
TestingEnvironmentCleaning:
type: object
required: [environment_id, erased_rows, cleaned_at]
properties:
environment_id: { type: string, format: uuid }
erased_rows: { type: integer, minimum: 0 }
cleaned_at: { type: string, format: date-time }
TestingApplicationImport:
type: object
required: [app_id]
additionalProperties: false
properties:
app_id:
$ref: '#/components/schemas/AppId'
description: Canonical production Application id to copy.
TestingApplicationImported:
type: object
required: [application, app_secret, app_secret_version, webhook_secret_inherited, secret_replay_expires_at]
additionalProperties: false
properties:
application: { $ref: '#/components/schemas/Application' }
app_secret:
type: string
pattern: '^ask_[A-Za-z0-9_-]{43}$'
description: Fresh credential valid only inside this testing environment.
app_secret_version: { type: integer, minimum: 1 }
webhook_secret_inherited:
type: boolean
const: true
description: Confirms that the production signing secret was inherited but not disclosed.
secret_replay_expires_at: { type: string, format: date-time }
TrustSelector:
type: object
additionalProperties: false
oneOf:
- required: [kind, tag_id]
properties: { kind: { const: tag }, tag_id: { type: string, format: uuid } }
- required: [kind, membership_id]
properties: { kind: { const: membership }, membership_id: { type: string, format: uuid } }
properties:
kind: { type: string, enum: [tag, membership] }
tag_id: { type: string, format: uuid }
membership_id: { type: string, format: uuid }
TrustRuleCreate:
type: object
required: [subject, target, trust]
additionalProperties: false
properties:
subject: { $ref: '#/components/schemas/TrustSelector' }
target: { $ref: '#/components/schemas/TrustSelector' }
trust: { $ref: '#/components/schemas/TrustValue' }
TrustRulePatch:
type: object
minProperties: 1
additionalProperties: false
properties:
subject: { $ref: '#/components/schemas/TrustSelector' }
target: { $ref: '#/components/schemas/TrustSelector' }
trust: { $ref: '#/components/schemas/TrustValue' }
TrustRule:
allOf:
- { $ref: '#/components/schemas/TrustRuleCreate' }
- type: object
required: [id, org_id, specificity, version, created_at, updated_at]
properties:
id: { type: string, format: uuid }
org_id: { $ref: '#/components/schemas/OrgId' }
specificity: { type: integer, minimum: 0, maximum: 2 }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
TrustRulePage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/TrustRule' } }
page: { $ref: '#/components/schemas/PageInfo' }
TrustEvaluationRequest:
type: object
required: [subject_membership_id, target_silicon_membership_id]
additionalProperties: false
properties:
subject_membership_id: { type: string, format: uuid }
target_silicon_membership_id: { type: string, format: uuid }
TrustEvaluation:
type: object
required: [trust, source, matching_rule_ids, advisory]
properties:
trust: { $ref: '#/components/schemas/TrustValue' }
source: { type: string, enum: [organization_default, tag_rule, exact_rule] }
matching_rule_ids: { type: array, items: { type: string, format: uuid } }
advisory: { const: true }
ApprovalKind: { type: string, enum: [carbon_job_role_change, silicon_job_role_change, carbon_tag_change, silicon_tag_change, silicon_token_rotation] }
ApprovalStatus: { type: string, enum: [pending, approved, rejected, completed] }
RoleChangeRequestCreate:
type: object
required: [target_membership_id, proposed_job_role]
additionalProperties: false
properties:
target_membership_id: { type: string, format: uuid }
proposed_job_role: { type: string, maxLength: 5000 }
reason: { type: [string, 'null'], maxLength: 2000 }
TagChangeRequestCreate:
type: object
additionalProperties: false
anyOf:
- required: [add_tag_ids]
properties:
add_tag_ids: { minItems: 1 }
- required: [remove_tag_ids]
properties:
remove_tag_ids: { minItems: 1 }
properties:
add_tag_ids:
type: array
uniqueItems: true
maxItems: 100
default: []
items: { type: string, format: uuid }
remove_tag_ids:
type: array
uniqueItems: true
maxItems: 100
default: []
items: { type: string, format: uuid }
reason: { type: [string, 'null'], minLength: 1, maxLength: 2000 }
DirectJobRoleReplace:
type: object
required: [job_role]
additionalProperties: false
properties:
job_role: { type: string, maxLength: 5000 }
DirectTagSetReplace:
type: object
required: [tag_ids]
additionalProperties: false
properties:
tag_ids:
type: array
uniqueItems: true
maxItems: 100
items: { type: string, format: uuid }
ApprovalDecisionCreate:
type: object
required: [decision]
additionalProperties: false
properties:
decision: { type: string, enum: [approve, reject] }
comment: { type: [string, 'null'], maxLength: 2000 }
ApprovalDecision:
type: object
required: [id, approver, decision, decided_at]
properties:
id: { type: string, format: uuid }
approver: { $ref: '#/components/schemas/ActorRef' }
decision: { type: string, enum: [approve, reject] }
comment: { type: [string, 'null'] }
decided_at: { type: string, format: date-time }
ApprovalRequest:
type: object
required: [id, org_id, kind, status, requested_by, target_membership_id, immutable_payload, required_approvals, decisions, version, created_at]
properties:
id: { type: string, format: uuid }
org_id: { $ref: '#/components/schemas/OrgId' }
kind: { $ref: '#/components/schemas/ApprovalKind' }
status: { $ref: '#/components/schemas/ApprovalStatus' }
requested_by: { $ref: '#/components/schemas/ActorRef' }
target_membership_id: { type: string, format: uuid }
immutable_payload: { type: object, additionalProperties: true }
required_approvals:
type: object
required: [target_carbon, eligible_owner_or_admin]
properties:
target_carbon: { type: integer, minimum: 0, maximum: 1 }
eligible_owner_or_admin: { type: integer, minimum: 1, maximum: 1 }
decisions: { type: array, items: { $ref: '#/components/schemas/ApprovalDecision' } }
completed_at: { type: [string, 'null'], format: date-time }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
ApprovalRequestPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/ApprovalRequest' } }
page: { $ref: '#/components/schemas/PageInfo' }
RoleHistory:
type: object
required: [id, membership_id, old_job_role, new_job_role, requested_by, approvers, approval_request_id, applied_at]
properties:
id: { type: string, format: uuid }
membership_id: { type: string, format: uuid }
old_job_role: { type: string }
new_job_role: { type: string }
requested_by: { $ref: '#/components/schemas/ActorRef' }
approvers: { type: array, items: { $ref: '#/components/schemas/ActorRef' } }
approval_request_id:
type: [string, 'null']
format: uuid
description: Null for an owner/admin direct change.
applied_at: { type: string, format: date-time }
RoleHistoryPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/RoleHistory' } }
page: { $ref: '#/components/schemas/PageInfo' }
TagHistory:
type: object
required: [id, membership_id, previous_tag_ids, applied_tag_ids, requested_by, approvers, approval_request_id, membership_version, applied_at]
properties:
id: { type: string, format: uuid }
membership_id: { type: string, format: uuid }
previous_tag_ids:
type: array
uniqueItems: true
maxItems: 100
items: { type: string, format: uuid }
applied_tag_ids:
type: array
uniqueItems: true
maxItems: 100
items: { type: string, format: uuid }
requested_by: { $ref: '#/components/schemas/ActorRef' }
approvers: { type: array, items: { $ref: '#/components/schemas/ActorRef' } }
approval_request_id:
type: [string, 'null']
format: uuid
description: Null for an owner/admin direct change.
membership_version: { type: integer, minimum: 1 }
applied_at: { type: string, format: date-time }
TagHistoryPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/TagHistory' } }
page: { $ref: '#/components/schemas/PageInfo' }
SsoEntitlement:
type: object
required: [enabled, version]
properties:
enabled: { type: boolean }
reason: { type: [string, 'null'], maxLength: 2000 }
version: { type: integer, minimum: 1 }
SsoConfiguration:
type: object
required: [org_id, entitled, status, join_method, version, updated_at]
properties:
org_id: { $ref: '#/components/schemas/OrgId' }
entitled: { type: boolean }
status: { type: string, enum: [disabled, pending, active, error] }
join_method: { type: string, enum: [email, sso] }
workos_organization_id: { type: [string, 'null'] }
connection_id: { type: [string, 'null'] }
version: { type: integer, minimum: 1 }
updated_at: { type: string, format: date-time }
SsoSetupLink:
type: object
required: [url, expires_in, expires_at]
properties:
url: { type: string, format: uri }
expires_in: { type: integer, const: 300 }
expires_at: { type: string, format: date-time }
TestResult:
type: object
required: [ok, checked_at]
properties:
ok: { type: boolean }
message: { type: [string, 'null'], maxLength: 1000 }
checked_at: { type: string, format: date-time }
ApplicationStatus:
type: string
enum: [under_review, verified, rejected, suspended, deleted]
ApplicationCreate:
type: object
required: [app_id, org_id, webhook_url, webhook_secret, base_url]
additionalProperties: false
description: Requires the authenticated Carbon to be a current active owner/admin of org_id.
properties:
app_id: { $ref: '#/components/schemas/ApplicationHandle' }
org_id: { $ref: '#/components/schemas/OrgId' }
app_name: { type: [string, 'null'], maxLength: 200 }
app_logo: { type: [string, 'null'], format: uri, maxLength: 2048 }
webhook_url: { type: string, format: uri, pattern: '^https://', maxLength: 2048 }
webhook_secret: { $ref: '#/components/schemas/ApplicationWebhookSecret' }
base_url:
type: string
format: uri
maxLength: 2048
description: >-
Pathless Application backend origin with no trailing slash,
credentials, query or fragment. HTTPS is required except for
literal loopback HTTP in local development.
obo_endpoints:
type: array
maxItems: 50
default: []
items: { $ref: '#/components/schemas/ApplicationOboEndpoint' }
ApplicationPatch:
type: object
minProperties: 1
additionalProperties: false
properties:
app_name: { type: [string, 'null'], maxLength: 200 }
app_logo: { type: [string, 'null'], format: uri, maxLength: 2048 }
base_url:
type: string
format: uri
maxLength: 2048
description: >-
Pathless backend origin without a trailing slash; HTTPS except for
literal loopback development.
obo_endpoints:
type: array
maxItems: 50
description: Full replacement. An empty array retires every active endpoint.
items: { $ref: '#/components/schemas/ApplicationOboEndpoint' }
Application:
type: object
required: [id, app_id, org_id, created_by, base_url, requested_scopes, approved_scopes, obo_endpoints, status, webhook, has_pending_changes, version, created_at, updated_at]
description: Organization-owned Application. created_by is immutable provenance and does not confer management authority.
properties:
id: { type: string, format: uuid }
app_id: { $ref: '#/components/schemas/AppId' }
org_id: { $ref: '#/components/schemas/OrgId' }
created_by: { $ref: '#/components/schemas/ActorRef' }
app_name: { type: [string, 'null'] }
app_logo: { type: [string, 'null'], format: uri }
base_url:
type: string
format: uri
maxLength: 2048
description: Pathless backend origin without a trailing slash.
requested_scopes: { type: array, uniqueItems: true, items: { type: string } }
approved_scopes: { type: array, uniqueItems: true, items: { type: string } }
obo_endpoints:
type: array
maxItems: 50
items: { $ref: '#/components/schemas/ApplicationOboEndpoint' }
status: { $ref: '#/components/schemas/ApplicationStatus' }
webhook: { $ref: '#/components/schemas/ApplicationWebhook' }
has_pending_changes: { type: boolean }
version: { type: integer, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
ApplicationCreated:
type: object
required: [application, app_secret, app_secret_version, webhook_signing_secret, webhook_secret_version, secret_replay_expires_at]
properties:
application: { $ref: '#/components/schemas/Application' }
app_secret: { type: string, pattern: '^ask_[A-Za-z0-9_-]{43}$' }
app_secret_version: { type: integer, minimum: 1 }
webhook_signing_secret: { $ref: '#/components/schemas/ApplicationWebhookSecret' }
webhook_secret_version: { type: integer, minimum: 1 }
secret_replay_expires_at: { type: string, format: date-time }
ApplicationSecretRotated:
type: object
required: [app_id, app_secret, app_secret_version, application_version, secret_replay_expires_at]
additionalProperties: false
properties:
app_id: { $ref: '#/components/schemas/AppId' }
app_secret: { type: string, pattern: '^ask_[A-Za-z0-9_-]{43}$' }
app_secret_version: { type: integer, minimum: 1 }
application_version: { type: integer, minimum: 1 }
secret_replay_expires_at: { type: string, format: date-time }
ApplicationWebhookSecretRotated:
type: object
required: [app_id, webhook_signing_secret, webhook_secret_version, application_version, secret_replay_expires_at]
additionalProperties: false
properties:
app_id: { $ref: '#/components/schemas/AppId' }
webhook_signing_secret: { $ref: '#/components/schemas/ApplicationWebhookSecret' }
webhook_secret_version: { type: integer, minimum: 1 }
application_version: { type: integer, minimum: 1 }
secret_replay_expires_at: { type: string, format: date-time }
ApplicationBaseUrl:
type: object
required: [app_id, base_url]
additionalProperties: false
properties:
app_id: { $ref: '#/components/schemas/AppId' }
base_url:
type: string
format: uri
maxLength: 2048
description: Pathless backend origin without a trailing slash.
ApplicationPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/Application' } }
page: { $ref: '#/components/schemas/PageInfo' }
AdminApplication:
allOf:
- { $ref: '#/components/schemas/Application' }
AdminApplicationPage:
type: object
required: [items, page]
properties:
items: { type: array, items: { $ref: '#/components/schemas/AdminApplication' } }
page: { $ref: '#/components/schemas/PageInfo' }
ApplicationWebhook:
type: object
required: [active_url, status, secret_version, version]
properties:
active_url:
type: [string, 'null']
format: uri
description: Null until the application's initial destination passes platform review.
pending_url: { type: [string, 'null'], format: uri }
status: { type: string, enum: [pending_review, active, replacement_under_review, disabled] }
secret_version: { type: integer, minimum: 1 }
webhook_signing_secret:
$ref: '#/components/schemas/ApplicationWebhookSecret'
description: >-
Echoes a caller-supplied replacement secret for v1 compatibility.
secret_replay_expires_at:
type: string
format: date-time
description: Present exactly when webhook_signing_secret is present.
version:
type: integer
minimum: 1
description: Application aggregate version; identical to the response ETag and the value required by If-Match for replacement.
ApplicationWebhookReplace:
type: object
required: [url]
additionalProperties: false
description: >-
Replaces only the reviewed destination candidate. It normally reuses
the existing encrypted signing secret. An imported test Application
still on its inherited production key must provide a new test-only
secret. Supplying a secret for any replacement installs it for the new
endpoint.
properties:
url: { type: string, format: uri, pattern: '^https://', maxLength: 2048 }
webhook_secret: { $ref: '#/components/schemas/ApplicationWebhookSecret' }
ApplicationWebhookSecret:
type: string
minLength: 32
maxLength: 512
pattern: '^[!-~]+$'
description: >-
Caller-chosen Application webhook signing secret containing only
non-whitespace ASCII characters. IAM encrypts it at rest and never
generates it.
ApplicationWebhookSecretRotate:
type: object
required: [webhook_secret]
additionalProperties: false
properties:
webhook_secret: { $ref: '#/components/schemas/ApplicationWebhookSecret' }
WebhookDeadLetter:
type: object
required: [delivery_id, event_id, event_type, occurred_at, aggregate_type, aggregate_id, aggregate_version, status, attempt_count, cycle_attempt_count, manual_replay_count, last_http_status, last_error_code, dead_lettered_at, version]
additionalProperties: false
properties:
delivery_id: { type: string, format: uuid }
event_id: { type: string, format: uuid }
event_type: { type: string }
occurred_at: { type: string, format: date-time }
aggregate_type: { type: string }
aggregate_id: { type: string, format: uuid }
aggregate_version: { type: integer, minimum: 1 }
status: { type: string, enum: [pending, dead_letter] }
attempt_count: { type: integer, minimum: 0 }
cycle_attempt_count: { type: integer, minimum: 0 }
manual_replay_count: { type: integer, minimum: 0 }
last_http_status: { type: [integer, 'null'], minimum: 100, maximum: 599 }
last_error_code: { type: [string, 'null'] }
dead_lettered_at: { type: [string, 'null'], format: date-time }
version: { type: integer, minimum: 1 }
WebhookDeadLetterPage:
type: object
required: [items, page]
additionalProperties: false
properties:
items: { type: array, items: { $ref: '#/components/schemas/WebhookDeadLetter' } }
page: { $ref: '#/components/schemas/PageInfo' }
WebhookReplayRequest:
type: object
required: [delivery_ids]
additionalProperties: false
properties:
delivery_ids:
type: array
minItems: 1
maxItems: 100
uniqueItems: true
items: { type: string, format: uuid }
WebhookReplayResponse:
type: object
required: [deliveries, replayed_count]
additionalProperties: false
properties:
deliveries:
type: array
maxItems: 100
items: { $ref: '#/components/schemas/WebhookDeadLetter' }
replayed_count: { type: integer, minimum: 1, maximum: 100 }
WebhookEvent:
type: object
required: [spec_version, event_id, event_type, occurred_at, aggregate, data]
properties:
spec_version: { const: '1.0' }
event_id: { type: string, format: uuid }
event_type:
type: string
pattern: '^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+\.v[1-9][0-9]*$'
description: Stable dotted event name with its positive schema version suffix.
occurred_at: { type: string, format: date-time }
organization_id: { type: [string, 'null'], format: uuid }
aggregate:
type: object
required: [id, type, version]
properties:
id: { type: string, format: uuid }
type: { type: string }
version: { type: integer, minimum: 1 }
data:
type: object
additionalProperties: true
description: >-
Event-type-specific authorized projection; never contains credentials or raw provider records.
For carbon.updated.v1, changed_fields and the complete current state are captured at the
aggregate version and filtered per Application by its effective after-change profile, email,
and phone consent scopes. The recipient union is authorized Applications immediately before
or after the change, so a before-only recipient receives no fields it can no longer read.
For the closed organization-member Application vocabulary (organization/ownership, tag,
trust, membership/directory/authorization, and Silicon lifecycle or completed credential
rotation events), recipient union, complete current state, and exact changed_fields are frozen
in the domain transaction and filtered by profile, organizations.read, memberships.read,
roles.read, and Carbon-only email/phone scopes. Member events always use
current.members as an array; organization.updated uses current.organization and requires
organizations.read; tag and trust events use current.resource plus current.members so their
independently versioned aggregate is retained. Before-only recipients keep union-scope-filtered
changed_fields but receive only stable resource/version authorization tombstones. Workers never
hydrate these events from later state. An affected resource is an Application-readable principal
or organization projection with an effective data scope; invitations, SSO/webhook configuration,
administrative/protocol controls, and an unassigned tag creation have no Application projection.
organization.membership.profile_updated.v1 and
rotation-request, configuration, subscription, and protocol/control events are excluded from
this Application projection vocabulary.
organization.membership.profile_updated.v1 is the organization-bound Silicon projection of
that mutation: it contains the changed non-contact profile fields, complete current membership
state, and before/after affected tags captured at the same Carbon version.
TestingWebhookEvent:
type: object
required: [test]
additionalProperties: false
description: >-
Explicit test-plane envelope. The signature covers these exact outer
bytes. testing_key is the environment root credential and must never
be logged or persisted with the event.
properties:
test:
type: object
required: [testing_key, metadata, data]
additionalProperties: false
properties:
testing_key: { $ref: '#/components/schemas/TestingEnvironmentKeyValue' }
metadata:
type: object
required: [spec_version, event_id, event_type, occurred_at, organization_id, aggregate]
additionalProperties: false
properties:
spec_version: { const: '1.0' }
event_id: { type: string, format: uuid }
event_type:
type: string
pattern: '^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+\.v[1-9][0-9]*$'
occurred_at: { type: string, format: date-time }
organization_id: { type: [string, 'null'], format: uuid }
aggregate:
type: object
required: [type, id, version]
additionalProperties: false
properties:
type: { type: string }
id: { type: string, format: uuid }
version: { type: integer, minimum: 1 }
data:
type: object
additionalProperties: true
SiliconFullEventType:
type: string
description: Exact closed 38-event vocabulary delivered by Silicon mode=all subscriptions.
enum:
- organization.membership.created.v1
- organization.membership.reactivated.v1
- organization.membership.removed.v1
- organization.silicon.created.v1
- organization.silicon.removed.v1
- organization.membership.updated.v1
- organization.membership.profile_updated.v1
- organization.membership.authorization_updated.v1
- organization.ownership_transferred.v1
- organization.admin.promoted.v1
- organization.admin.demoted.v1
- organization.silicon.updated.v1
- organization.tag_updated.v1
- organization.trust.default_updated.v1
- organization.trust.rule_created.v1
- organization.trust.rule_updated.v1
- organization.trust.rule_archived.v1
- organization.created.v1
- organization.updated.v1
- organization.tag_created.v1
- organization.invitation.created.v1
- organization.invitation.accepted.v1
- organization.invitation.revoked.v1
- organization.role_change.requested.v1
- organization.tag_change.requested.v1
- organization.approval.decided.v1
- organization.silicon.rotation_requested.v1
- organization.silicon.credential_rotated.v1
- organization.silicon.webhook.configured.v1
- organization.silicon.webhook.deleted.v1
- organization.silicon.webhook_subscription.updated.v1
- organization.silicon.webhook_subscription.deleted.v1
- sso.setup_link.created.v1
- sso.configuration.disabled.v1
- sso.entitlement.replaced.v1
- sso.connection.activated.v1
- sso.connection.deactivated.v1
- sso.connection.deleted.v1
SiliconWebhookEvent:
allOf:
- { $ref: '#/components/schemas/WebhookEvent' }
- type: object
required: [event_type]
properties:
event_type: { $ref: '#/components/schemas/SiliconFullEventType' }
ApplicationAdminDecision:
type: object
required: [decision]
additionalProperties: false
description: >-
Platform transition for an application that is already in use.
Applications arrive verified, so this suspends, reactivates, rejects or
deletes one rather than admitting it. delete is terminal, requires all
application administration capabilities plus verified-channel step-up,
and accepts reason only; approved_scopes is rejected.
properties:
decision: { type: string, enum: [approve, reject, suspend, reactivate, delete, approve_pending_changes, reject_pending_changes] }
approved_scopes: { type: array, uniqueItems: true, items: { type: string } }
reason: { type: [string, 'null'], maxLength: 2000 }
ApplicationOboEndpoint:
type: object
required: [endpoint_id, path, metadata]
additionalProperties: false
description: Callable endpoint definition configurable only by a current owner/admin of the Application's organization.
properties:
endpoint_id:
type: string
minLength: 3
maxLength: 128
pattern: '^[a-z][a-z0-9_.:-]{2,127}$'
description: Stable identifier; an existing identifier cannot be assigned a different path.
path:
type: string
minLength: 1
maxLength: 2048
pattern: '^/(?!/)(?!.*(?:^|/)\.\.?(?:/|$))(?!.*[?#\x00-\x20\x7F]).*$'
description: Stable absolute audience-application endpoint path.
metadata:
type: object
additionalProperties: true
description: Each top-level key is required at exchange. A descriptor may declare type as string, number, integer, boolean, object, array, or null; size, nesting, and node count are bounded.
OboEndpointReference:
type: object
required: [endpoint_id, path]
additionalProperties: false
properties:
endpoint_id: { type: string, pattern: '^[a-z][a-z0-9_.:-]{2,127}$' }
path: { type: string, maxLength: 2048 }
OboApplicationReference:
type: object
required: [app_id, org_id]
additionalProperties: false
properties:
app_id: { $ref: '#/components/schemas/AppId' }
org_id: { $ref: '#/components/schemas/OrgId' }
OboEndpointCatalog:
type: object
required: [application, endpoints]
additionalProperties: false
properties:
application: { $ref: '#/components/schemas/OboApplicationReference' }
endpoints:
type: array
maxItems: 50
description: Active definitions ordered by endpoint_id.
items: { $ref: '#/components/schemas/ApplicationOboEndpoint' }
OboRequestMethod:
type: string
minLength: 1
maxLength: 32
pattern: "^[A-Z][A-Z0-9!#$%&'*+.^_`|~-]{0,31}$"
description: Canonical uppercase HTTP method included byte-for-byte in the OBO HMAC and proof binding.
OboBodySha256:
type: string
pattern: '^[0-9a-f]{64}$'
description: Lowercase hexadecimal SHA-256 digest of the exact downstream request body bytes.
OboExchangeRequestBinding:
type: object
required: [method, body_sha256]
additionalProperties: false
properties:
method: { $ref: '#/components/schemas/OboRequestMethod' }
body_sha256: { $ref: '#/components/schemas/OboBodySha256' }
OboVerifyRequestBinding:
type: object
required: [method, path, body_sha256]
additionalProperties: false
properties:
method: { $ref: '#/components/schemas/OboRequestMethod' }
path:
type: string
minLength: 1
maxLength: 2048
pattern: '^/(?!/)(?!.*(?:^|/)\.\.?(?:/|$))(?!.*[?#\x00-\x20\x7F]).*$'
description: Exact registered path of the downstream request.
body_sha256: { $ref: '#/components/schemas/OboBodySha256' }
OboExchangeRequest:
type: object
required: [subject_token, audience, endpoint_id, metadata, request]
additionalProperties: false
description: Organization is derived from App A and App B; org_id and X-Org-ID are not accepted.
properties:
subject_token: { type: string, minLength: 32, maxLength: 4096, description: Actor-bound application access token issued to the calling app. }
audience: { $ref: '#/components/schemas/AppId' }
endpoint_id: { type: string, minLength: 3, maxLength: 128, pattern: '^[a-z][a-z0-9_.:-]{2,127}$' }
metadata:
type: object
additionalProperties: true
description: Exact metadata bound into the proof. It must contain every registered key, no unregistered keys, and values matching every declared type.
request: { $ref: '#/components/schemas/OboExchangeRequestBinding' }
OboProofResponse:
type: object
required: [access_proof, proof_id, expires_in, expires_at]
additionalProperties: false
description: The idempotency replay envelope for this secret response expires no later than expires_at.
properties:
access_proof: { type: string, pattern: '^obo_[A-Za-z0-9_-]{43}$' }
proof_id: { type: string, format: uuid }
expires_in: { type: integer, minimum: 1, maximum: 60, default: 60 }
expires_at: { type: string, format: date-time }
OboVerifyRequest:
type: object
required: [access_proof, request]
additionalProperties: false
description: Exact actual-request binding; successful verification is strictly single-use and not idempotently replayable.
properties:
access_proof: { type: string, pattern: '^obo_[A-Za-z0-9_-]{43}$' }
request: { $ref: '#/components/schemas/OboVerifyRequestBinding' }
OboAccessResult:
type: object
required: [valid, proof_id, issuer_app_id, audience, actor, authorization, org_id, endpoint, metadata, expires_at, consumed_at]
properties:
valid: { const: true }
proof_id: { type: string, format: uuid }
issuer_app_id: { $ref: '#/components/schemas/AppId' }
audience: { $ref: '#/components/schemas/AppId' }
actor: { $ref: '#/components/schemas/ActorRef' }
authorization: { $ref: '#/components/schemas/ApplicationAuthorization' }
org_id: { $ref: '#/components/schemas/OrgId' }
endpoint: { $ref: '#/components/schemas/OboEndpointReference' }
metadata: { type: object, additionalProperties: true }
expires_at: { type: string, format: date-time }
consumed_at: { type: string, format: date-time }