The descriptions of the operations and fields are the contract’s own, in English.
/identity/v1/contextRead the caller's own resolved context
- Credential
- API key
- Permission
- None beyond the credential
A self-read for any authenticated credential. It needs no permission (its whole purpose is to tell the caller what it may do), changes nothing, names no other principal and is not recorded as an auditable action.
Read more
It renders the caller's identity (the credential's class and reference, and its own account when it has one), the organization the request acts in, its roles (organization-level, per team and platform), the permissions it holds resolved against the closed vocabulary (organization-wide, for every team, per team and, at platform level, the operator set) so that a team-scoped check can be answered, the roles it may assign to others, and the organization's active entitlements. The boundary's own gates have already passed by the time it is answered: an organization that is provisioning, suspended, disabled or deleted, or a disabled user account, never reaches it (403 with organization-provisioning, organization-suspended, organization-disabled, organization-deleted or user-disabled). Selecting the organization: X-Organization-Id selects one of the caller's active organization memberships; a person with a single membership needs none, with several none is 403 organization-selection-required, a value that is not one of their memberships is 403 organization-not-selectable, and no active membership at all is 403 no-active-organization-membership. Ordinary service API keys keep their fixed organization; personal API keys reach inference and the MCP endpoint only and cannot call this endpoint. A platform administrator credential (an API key stamped with platform authority and a current platform-administrator assignment) may select a local managed organization it holds no membership in, and so may a platform operator: a human signed in through OIDC whose account holds the ACTIVE platform ccsio_admin role (read fresh on every request, never cached) may select any existing organization. A platform operator resolves no platform role (roles.platform stays empty) and carries the fixed operator permission set described in the introduction of this API, which permissions.platform lists exactly; it does not include models.register, nor any of the organization- and team-level permissions a platform ccsio_admin key holds everywhere (members, API keys, inference, ...). In an organization where the operator holds no membership the context carries only the operator set and no role bindings (permissions.organization lists organization.create alone, the entry the console's Create organization is gated on); in their own organizations their role bindings apply as for any member, plus the operator set. permissions.platform is empty for every principal that holds no platform authority. X-Team-Id selects one active team membership of the selected organization and comes back as selected_team_id; a team the caller is not an active member of is 403 team-not-selectable. Staff operators: on a plane that trusts a staff issuer (the identity provider of the platform's own operators, the backoffice's), a token of that issuer whose bearer holds the operator role there is a platform operator who belongs to no organization. With no X-Organization-Id the answer is the platform context (organization null, permissions.platform the operator set); with it, the operator's view of that organization (the operator set, no role of the organization, even where the person is also a member). Such a token without the role is 401 staff-not-operator, with its session ended 401 staff-token-inactive, and when the staff issuer cannot confirm it 401 staff-directory-unavailable. In the platform context every route that works on one organization answers 403 organization-selection-required.
curl "https://console.latam.ccsio.ai/identity/v1/context" \
-H "Authorization: Bearer $CCSIO_API_KEY"Parameters
| Name | In | Description |
|---|---|---|
X-Request-IDoptional | header | string Optional request ULID. A valid ULID (upper or lowercase) is honored; when the header is absent or invalid, the runtime mints the id. The response X-Request-ID header carries the canonical uppercase form. |
X-Organization-Idoptional | header | string Selects one of the authenticated human's active organization memberships. The server resolves and verifies this selection into trusted context; request bodies cannot choose the owner or organization. Read moreA platform operator (a human whose user holds the active platform role ccsio_admin) may also select ANY existing organization: where they hold no membership the context carries only the platform operator permission set and no role bindings. For every other human, naming an organization they hold no active membership in is refused with 403 organization-not-selectable. |
X-Team-Idoptional | header | string Selects one of the authenticated human's active team memberships in the selected organization; the answer then names it as selected_team_id. A team the person is not an active member of is refused with 403 team-not-selectable. |
Responses
- 200
The caller's own context.
Schema
TrustedContextselected_team_idstringoptionalThe team selected with X-Team-Id, verified against a fresh active team membership; left out when no selector was sent.
pattern ^[a-z][a-z0-9._-]{0,63}$
schema_versionintegerrequiredAllowed values:
1identityobjectrequiredThe verified principal. It carries no organization: organization.organization_id does.
classstringrequiredThe kind of credential the request authenticated with, not of the person or account behind it: service for every API-key request (a key issued to a human still reads service here) and user for a signed-in session. To tell a person from a service account, read user.kind.
Allowed values:
"user""service"refstringrequiredThe principal's reference.
pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$
userobject or nullrequiredThe principal's own account. null when it has none (for example an API key whose principal was never provisioned as a user). When present, user.kind says whether the subject is a human or a service account.
user_idstringrequiredkindstringrequiredAllowed values:
"human""service_account"display_namestringrequiredemailstringrequiredstatusstringrequiredAllowed values:
"active""disabled"
organizationobject or nullrequiredThe organization the request acts in. null in the platform context: a platform operator signed in at the staff issuer who sent no X-Organization-Id. Such a context has no organization, no roles and no entitlements; permissions.platform is the operator set and every other permission list is empty.
organization_idstringrequiredpattern ^[a-z][a-z0-9._-]{0,63}$
display_namestringrequired1 to 128 characters
statusstringrequiredAllowed values:
"provisioning""active""suspended""disabled""deleted"residencystringrequiredAllowed values:
"eu""us""latam"
rolesobjectrequiredThe roles the caller holds, by scope. Each list is sorted and free of duplicates, teams is sorted by team_id, and none is ever null: a list is empty where the caller holds nothing at that scope.
organizationarray of stringrequiredThe role ids of the caller's organization-level role bindings (a built-in role id, or a custom role's id).
teamsarray of TrustedContextTeamRolerequiredOne entry per team-level role binding the caller holds, sorted by team_id.
team_idstringrequiredpattern ^[a-z][a-z0-9._-]{0,63}$
rolestringrequiredThe role id: a built-in role id, or a custom role's id.
platformarray of stringrequiredThe platform roles the caller holds, such as ccsio_admin; a platform operator signed in with a session holds none here and carries the operator permission set instead.
permissionsobjectrequiredWhat the caller may do, resolved against the closed permission vocabulary and split so that a team-scoped check is answerable: the caller holds a permission for a team when it is in organization, in all_teams, or in teams for that team (a flat list cannot say that a permission is held for one team and not another). Every list is in the vocabulary's canonical order and never null.
organizationarray of PermissionrequiredThe permissions the caller holds organization-wide, from its organization-level role bindings and platform roles.
Allowed values:
"organization.create""organization.read""organization.update""organization.delete""organization.status""teams.read""teams.read_own""teams.create""teams.update""teams.archive""team-members.read""team-members.manage""members.read""members.manage""members.transfer""users.read""users.manage""roles.read""roles.manage""sso.manage""api-keys.read""api-keys.manage""entitlements.read""entitlements.manage""team-entitlements.manage""issuers.read""issuers.manage""models.read""models.manage""models.register""model-registrars.manage""platform-operators.read""platform-operators.manage""registry.manage""platform-usage.read""support-sessions.start""support-sessions.manage""support-access.read""deployments.read""deployments.manage""model-groups.read""model-groups.manage""memory.read""memory.manage""audit.read""audit.read_own""audit.sensitive.read""usage.read""usage.read_own""usage.manage""inference.invoke""inference.read""mcp.invoke""mcp.read""mcp.manage""model-providers.manage"all_teamsarray of PermissionrequiredThe team-scoped permissions the caller holds for every team of the organization: an organization administrator, the holder of an organization-level custom role, or a platform ccsio_admin.
Allowed values:
"organization.create""organization.read""organization.update""organization.delete""organization.status""teams.read""teams.read_own""teams.create""teams.update""teams.archive""team-members.read""team-members.manage""members.read""members.manage""members.transfer""users.read""users.manage""roles.read""roles.manage""sso.manage""api-keys.read""api-keys.manage""entitlements.read""entitlements.manage""team-entitlements.manage""issuers.read""issuers.manage""models.read""models.manage""models.register""model-registrars.manage""platform-operators.read""platform-operators.manage""registry.manage""platform-usage.read""support-sessions.start""support-sessions.manage""support-access.read""deployments.read""deployments.manage""model-groups.read""model-groups.manage""memory.read""memory.manage""audit.read""audit.read_own""audit.sensitive.read""usage.read""usage.read_own""usage.manage""inference.invoke""inference.read""mcp.invoke""mcp.read""mcp.manage""model-providers.manage"teamsarray of TrustedContextTeamPermissionsrequiredOnly the teams where the caller holds a team-level role binding, sorted by team_id.
team_idstringrequiredpattern ^[a-z][a-z0-9._-]{0,63}$
permissionsarray of PermissionrequiredThe permissions of the caller's role binding in this team.
platformarray of PermissionrequiredThe permissions the caller holds at platform level, whichever organization the request resolved to. For a platform operator (a human whose account holds the active platform role ccsio_admin) exactly the fixed operator permission set listed in the description of this API. For a credential with a platform role, that role's permissions (a ccsio_admin key: every permission; a model registrar: models.register). Empty for every other principal. The console gates its platform navigation on it.
Allowed values:
"organization.create""organization.read""organization.update""organization.delete""organization.status""teams.read""teams.read_own""teams.create""teams.update""teams.archive""team-members.read""team-members.manage""members.read""members.manage""members.transfer""users.read""users.manage""roles.read""roles.manage""sso.manage""api-keys.read""api-keys.manage""entitlements.read""entitlements.manage""team-entitlements.manage""issuers.read""issuers.manage""models.read""models.manage""models.register""model-registrars.manage""platform-operators.read""platform-operators.manage""registry.manage""platform-usage.read""support-sessions.start""support-sessions.manage""support-access.read""deployments.read""deployments.manage""model-groups.read""model-groups.manage""memory.read""memory.manage""audit.read""audit.read_own""audit.sensitive.read""usage.read""usage.read_own""usage.manage""inference.invoke""inference.read""mcp.invoke""mcp.read""mcp.manage""model-providers.manage"
assignable_rolesobjectrequiredWhich roles the caller may grant to others; it feeds the role pickers of the console. Every list is sorted, free of duplicates and never null; teams is sorted by team_id.
organizationarray of stringrequiredThe roles assignable through the organization-level membership routes: the built-in roles the caller may grant and the custom role ids whose permissions it holds. A holder of custom roles only never sees root, organization_admin or team_admin here.
teamsarray of TrustedContextTeamAssignableRolesrequiredOne entry per team the caller holds an active role binding in, sorted by team_id; its roles list is empty (the entry is not left out) for a team where the caller is not an administrator.
team_idstringrequiredpattern ^[a-z][a-z0-9._-]{0,63}$
rolesarray of stringrequired
all_teamsarray of stringrequiredThe union of every team's assignable set or, for an organization-wide administrator, the full team-level roster in one pass.
entitlementsarray of TrustedContextEntitlementrequiredThe organization's active entitlements: its own, the team-scoped ones of the teams the caller is an active member of, and the models it reaches through a model group (shown as organization-scoped model access). Never null; empty where the organization holds none.
capabilitystringrequiredAllowed values:
"model_access""brain_capacity""billing_state""feature"model_refstringrequiredThe model reference; empty unless capability is model_access.
team_idstring or nullrequirednull for an organization-scoped entitlement; the team's id for a team-scoped one.
pattern ^[a-z][a-z0-9._-]{0,63}$
feature_keystringrequiredThe feature key; empty unless capability is feature.
Allowed values:
"""memory.connectors""memory.zero_content_retention"capacity_quantityintegerrequiredBrain capacity's amount; 0 unless capability is brain_capacity.
at least 0
capacity_unitstringrequiredBrain capacity's unit (gigabytes of indexed content; provisional, and the only unit today); empty unless capability is brain_capacity.
Allowed values:
"""gb"
- 400
Client refusal unrelated to authentication, including malformed input, a denied or failed request.
- 401
The request carries no credential, more than one, or one the platform does not accept, and is refused before the operation runs; `error.code` says why. Supply exactly one credential. Codes: invalid-request (no credential, or both Authorization:
Read more
Bearer and x-api-key), api-key-invalid (a value that is not a platform API key, or a key of a kind the platform does not accept), api-key-unknown, api-key-revoked, api-key-expired, bootstrap-disabled (the one-shot installation credential, once a key exists), token-malformed (a bearer token that is not a JWT), token-algorithm-unsupported, token-signature-invalid, token-claim-invalid, token-issuer-mismatch, token-audience-mismatch, token-expired, token-not-yet-valid, issuer-untrusted, issuer-residency-mismatch (the issuer belongs to another plane), issuer-resolution-unknown, jwks-unavailable, jwks-key-not-found, staff-token-inactive (a platform operator's token), staff-not-operator, staff-directory-unavailable, identity-not-provisioned (a verified identity with no account on this plane), organization-not-found (a verified identity or key whose organization this plane does not know), internal-error (a fault while the credential is checked is refused too, fail closed), context-cancelled
- 403
The credential is valid but may not do this here; the request is refused by the request boundary before the handler runs, and `error.code` says which refusal. An operation may add codes of its own.
Read more
Codes: policy-denied (no role of the caller holds the permission the operation needs, or the credential class may not call it: a personal API key outside inference and MCP, a route that needs a signed-in person, the one-shot installation credential outside its three steps), tenant-mismatch (the organization a path, query, body or X-Tenant header names is not the caller's own), organization-provisioning, organization-suspended, organization-disabled, organization-deleted (the state of the caller's organization), user-disabled, residency-mismatch (the organization lives on another plane), organization-selection-required (a caller with more than one organization, or a platform operator, must name one in X-Organization-Id), organization-not-selectable, no-active-organization-membership, team-not-selectable (the X-Organization-Id or X-Team-Id the caller sent does not name an organization or team it may act in), identity-managed-by-provider (a person who is not a platform operator changes an organization's status, which belongs to the identity provider), support-session-required (a platform operator reads an organization's data without an open support session)
- 404
The requested resource or path was not found.
- 405
The path is claimed but the request method is not allowed. Go ServeMux returns its standard plain-text response and lists permitted methods in Allow.
- 500
Platform failure, rendered without internal cause details.
{
"schema_version": 1,
"identity": {
"class": "user",
"ref": "user/onboard/01K7YN1B3C5D7F9H2K4M6P8R0T",
"user": {
"user_id": "01K7YN1B3C5D7F9H2K4M6P8R0T",
"kind": "human",
"display_name": "Ana García",
"email": "[email protected]",
"status": "active"
}
},
"organization": {
"organization_id": "acme",
"display_name": "Acme Corp",
"status": "active",
"residency": "eu"
},
"roles": {
"organization": [
"user"
],
"teams": [
{
"team_id": "platform",
"role": "team_admin"
}
],
"platform": []
},
"permissions": {
"organization": [
"organization.read",
"teams.read_own",
"models.read",
"usage.read_own",
"inference.invoke",
"inference.read",
"mcp.invoke",
"mcp.read"
],
"all_teams": [],
"teams": [
{
"team_id": "platform",
"permissions": [
"organization.read",
"teams.read",
"teams.read_own",
"teams.update",
"team-members.read",
"team-members.manage",
"members.read",
"users.read",
"roles.read",
"entitlements.read",
"models.read",
"memory.read",
"memory.manage",
"audit.read_own",
"usage.read",
"usage.read_own",
"usage.manage",
"inference.invoke",
"inference.read",
"mcp.invoke",
"mcp.read"
]
}
],
"platform": []
},
"assignable_roles": {
"organization": [],
"teams": [
{
"team_id": "platform",
"roles": [
"team_admin",
"user"
]
}
],
"all_teams": [
"team_admin",
"user"
]
},
"entitlements": [
{
"capability": "model_access",
"model_ref": "glm-5.3",
"team_id": null,
"feature_key": "",
"capacity_quantity": 0,
"capacity_unit": ""
},
{
"capability": "model_access",
"model_ref": "qwen3-embedding",
"team_id": "platform",
"feature_key": "",
"capacity_quantity": 0,
"capacity_unit": ""
}
]
}/identity/v1/self/organizationsDiscover the organizations the caller can select
- Credential
- API key
- Permission
- None beyond the credential
Lists the organizations of this plane (its data residency) that the authenticated caller can select, before any organization is selected. It needs no permission, takes no X-Organization-Id and is never widened by a client selector.
Read more
A person signed in through OIDC gets the active organizations of their fresh active memberships, unless their account holds the platform ccsio_admin role (read fresh on every request, never cached): such a person is a platform operator and discovers every organization of this plane, in the same shape and order, as the discovery half of the right to select any existing organization with X-Organization-Id (see GET /identity/v1/context); for every other person, selecting an organization they hold no membership in is refused. A platform operator signed in at the staff issuer belongs to no organization and also gets every organization of this plane. Ordinary service API keys see only their fixed organization. A platform API key with a current platform-administrator assignment discovers the manageable organizations of this plane, locally inactive ones included. Personal API keys reach inference and the MCP endpoint only and cannot call this endpoint. Where an organization is linked to the identity provider, the provider's own access check still applies to every organization either kind of administrator lists.
curl "https://console.latam.ccsio.ai/identity/v1/self/organizations" \
-H "Authorization: Bearer $CCSIO_API_KEY"Parameters
| Name | In | Description |
|---|---|---|
X-Request-IDoptional | header | string Optional request ULID. A valid ULID (upper or lowercase) is honored; when the header is absent or invalid, the runtime mints the id. The response X-Request-ID header carries the canonical uppercase form. |
Responses
- 200
The organizations the caller can select: its fresh active memberships, or every organization of this residency for a platform administrator. A platform operator may select any listed organization with X-Organization-Id; for any other person a listed organization is a membership.
Schema
SelfOrganizationsorganizationsarray of SelfOrganizationrequiredorganization_idstringrequireddisplay_namestringrequiredaliasOrganizationAlias or nullrequiredThe organization's alias; null while it has none (an alias exists only for an organization with single sign-on).
residencystringrequiredAllowed values:
"eu""us""latam"statusstringrequiredAllowed values:
"provisioning""active""suspended""disabled""deleted"
- 400
Client refusal unrelated to authentication, including malformed input, a denied or failed request.
- 401
The request carries no credential, more than one, or one the platform does not accept, and is refused before the operation runs; `error.code` says why. Supply exactly one credential. Codes: invalid-request (no credential, or both Authorization:
Read more
Bearer and x-api-key), api-key-invalid (a value that is not a platform API key, or a key of a kind the platform does not accept), api-key-unknown, api-key-revoked, api-key-expired, bootstrap-disabled (the one-shot installation credential, once a key exists), token-malformed (a bearer token that is not a JWT), token-algorithm-unsupported, token-signature-invalid, token-claim-invalid, token-issuer-mismatch, token-audience-mismatch, token-expired, token-not-yet-valid, issuer-untrusted, issuer-residency-mismatch (the issuer belongs to another plane), issuer-resolution-unknown, jwks-unavailable, jwks-key-not-found, staff-token-inactive (a platform operator's token), staff-not-operator, staff-directory-unavailable, identity-not-provisioned (a verified identity with no account on this plane), organization-not-found (a verified identity or key whose organization this plane does not know), internal-error (a fault while the credential is checked is refused too, fail closed), context-cancelled
- 403
The credential is valid but may not do this here; the request is refused by the request boundary before the handler runs, and `error.code` says which refusal. An operation may add codes of its own.
Read more
Codes: policy-denied (no role of the caller holds the permission the operation needs, or the credential class may not call it: a personal API key outside inference and MCP, a route that needs a signed-in person, the one-shot installation credential outside its three steps), tenant-mismatch (the organization a path, query, body or X-Tenant header names is not the caller's own), organization-provisioning, organization-suspended, organization-disabled, organization-deleted (the state of the caller's organization), user-disabled, residency-mismatch (the organization lives on another plane), organization-selection-required (a caller with more than one organization, or a platform operator, must name one in X-Organization-Id), organization-not-selectable, no-active-organization-membership, team-not-selectable (the X-Organization-Id or X-Team-Id the caller sent does not name an organization or team it may act in), identity-managed-by-provider (a person who is not a platform operator changes an organization's status, which belongs to the identity provider), support-session-required (a platform operator reads an organization's data without an open support session)
- 404
The requested resource or path was not found.
- 405
The path is claimed but the request method is not allowed. Go ServeMux returns its standard plain-text response and lists permitted methods in Allow.
- 500
Platform failure, rendered without internal cause details.
/identity/v1/self/session-eventsReport a login or logout of the signed-in human
- Credential
- A signed-in person’s token (Console session)
- Permission
- None beyond the credential
- Request body
- Body up to 1 MiB
Called by the portal after the OIDC callback and on logout. Requires a verified human OIDC session; an API key, a personal key or the bootstrap credential is 403 policy-denied.
Read more
No organization is selected: core records ONE security event per organization the caller holds an active membership in (user.login or user.logout, actor and subject both the caller, with the client IP address and user agent the request carried), atomically. The route is not itself sensitive - it writes its own events. A failed write is a 500 (the portal decides whether to retry).
curl -X POST "https://console.latam.ccsio.ai/identity/v1/self/session-events" \
-H "Authorization: Bearer $CCSIO_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event": "login",
"session_ref": "string"
}'Parameters
| Name | In | Description |
|---|---|---|
X-Request-IDoptional | header | string Optional request ULID. A valid ULID (upper or lowercase) is honored; when the header is absent or invalid, the runtime mints the id. The response X-Request-ID header carries the canonical uppercase form. |
Request body application/json
eventstringrequiredAllowed values:
"login""logout"session_refstringrequiredAn opaque correlation of one login session, 1 to 128 characters; the portal chooses it and reuses it for the matching logout.
pattern ^[A-Za-z0-9._:-]{1,128}$
Responses
- 204
The event was recorded (also when the user belongs to no organization yet: there is no log to write to).
- 400
Client refusal unrelated to authentication, including malformed input, a denied or failed request.
- 401
The request carries no credential, more than one, or one the platform does not accept, and is refused before the operation runs; `error.code` says why. Supply exactly one credential. Codes: invalid-request (no credential, or both Authorization:
Read more
Bearer and x-api-key), api-key-invalid (a value that is not a platform API key, or a key of a kind the platform does not accept), api-key-unknown, api-key-revoked, api-key-expired, bootstrap-disabled (the one-shot installation credential, once a key exists), token-malformed (a bearer token that is not a JWT), token-algorithm-unsupported, token-signature-invalid, token-claim-invalid, token-issuer-mismatch, token-audience-mismatch, token-expired, token-not-yet-valid, issuer-untrusted, issuer-residency-mismatch (the issuer belongs to another plane), issuer-resolution-unknown, jwks-unavailable, jwks-key-not-found, staff-token-inactive (a platform operator's token), staff-not-operator, staff-directory-unavailable, identity-not-provisioned (a verified identity with no account on this plane), organization-not-found (a verified identity or key whose organization this plane does not know), internal-error (a fault while the credential is checked is refused too, fail closed), context-cancelled
- 403
The credential is valid but may not do this here; the request is refused by the request boundary before the handler runs, and `error.code` says which refusal. An operation may add codes of its own.
Read more
Codes: policy-denied (no role of the caller holds the permission the operation needs, or the credential class may not call it: a personal API key outside inference and MCP, a route that needs a signed-in person, the one-shot installation credential outside its three steps), tenant-mismatch (the organization a path, query, body or X-Tenant header names is not the caller's own), organization-provisioning, organization-suspended, organization-disabled, organization-deleted (the state of the caller's organization), user-disabled, residency-mismatch (the organization lives on another plane), organization-selection-required (a caller with more than one organization, or a platform operator, must name one in X-Organization-Id), organization-not-selectable, no-active-organization-membership, team-not-selectable (the X-Organization-Id or X-Team-Id the caller sent does not name an organization or team it may act in), identity-managed-by-provider (a person who is not a platform operator changes an organization's status, which belongs to the identity provider), support-session-required (a platform operator reads an organization's data without an open support session)
- 405
The path is claimed but the request method is not allowed. Go ServeMux returns its standard plain-text response and lists permitted methods in Allow.
- 500
Platform failure, rendered without internal cause details.
- 503
A dependency the operation needs is not configured on this plane or could not be reached, and nothing was changed. `error.code` names it; an operation lists the ones it can answer besides the boundary's. Retry later. Codes: support-audit-unavailable (the request boundary: an operator's read under an open support session could not be recorded, so nothing was served)
Generated from the platform contracts at commit 5f833620.