API reference: SAML & SCIM
Cloud Control SAML 2.0 SSO endpoints (metadata, SP-initiated login, ACS), the per-organization SAML/SCIM/group-mapping configuration APIs, and the SCIM 2.0 provisioning surface (Users, Groups, discovery).
SAML 2.0 sign-in (public)
/api/auth/saml/metadataPublicSP metadata XML (entity ID + HTTP-POST ACS). Import this into your IdP.
<md:EntityDescriptor entityID="https://host/api/auth/saml/metadata">…</md:EntityDescriptor>/api/auth/saml/loginPublicBegin SP-initiated SSO: match the work email domain / org slug to an enabled SAML config and return the IdP redirect URL (deflate+base64 AuthnRequest).
| Name | In | Required | Description |
|---|---|---|---|
email | body | no | Work email (its domain is matched). |
slug | body | no | Organization slug (alternative to email). |
{ "email": "alice@corp.example" }{ "ok": true, "redirectUrl": "https://idp/sso?SAMLRequest=…&RelayState=…", "requestId": "_abc…" }| Status | When |
|---|---|
404 | SAML isn't configured for that domain/org (enumeration-safe, generic). |
/api/auth/saml/acsPublic (form POST binding)Assertion Consumer Service: verify the signed assertion (exc-c14n + RSA-SHA256, Conditions, single-use replay), JIT-match by email with the group-mapped role, and set a session cookie (303 to /).
| Name | In | Required | Description |
|---|---|---|---|
SAMLResponse | body | yes | base64 SAML Response (application/x-www-form-urlencoded). |
RelayState | body | no | Round-tripped from the AuthnRequest. |
| Status | When |
|---|---|
303 | Success — redirect to / with a session cookie. |
400 | Bad/expired/replayed/unsigned/tampered assertion, wrong audience, or InResponseTo mismatch (generic). |
403 | The organization is suspended. |
SAML config (Org Admin, session only)
/api/org/samlOrg Admin (session only)Create/update the org's SAML config. Accepts pasted IdP metadata XML (auto-fills entity ID / SSO URL / cert) or explicit fields. The signing certificate is validated on save.
| Name | In | Required | Description |
|---|---|---|---|
metadataXml | body | no | IdP metadata XML — entity ID / SSO URL / cert are extracted from it. |
idpEntityId | body | no | IdP entity ID (required if no metadata). |
ssoUrl | body | no | IdP SSO URL (https). |
certificate | body | no | IdP X.509 signing cert (PEM or base64). Public value. |
defaultRole | body | no | Role when no group maps; default Viewer. |
emailDomains | body | no | Domains routed to this IdP. |
attrEmail | body | no | Assertion attribute for email (blank ⇒ NameID). |
attrGroups | body | no | Assertion attribute for group membership. |
{ "ok": true, "saml": { "idpEntityId": "…", "ssoUrl": "…", "certificateSet": true, "defaultRole": "Viewer", "emailDomains": ["corp.example"], "attrGroups": "groups", "enabled": true } }| Status | When |
|---|---|
400 | Missing entity ID, non-https SSO URL, unusable certificate, bad role/domains, or unparseable metadata. |
403 | Caller lacks manage_users_sso. |
GET /api/org/saml returns the config (cert never echoed, only certificateSet); PATCH /api/org/saml toggles { enabled }.
SCIM tokens & group mappings (Org Admin, session only)
/api/org/scimOrg Admin (session only)Issue a per-org SCIM bearer token (cc_scim_…, shown once) and the SCIM base URL.
{ "ok": true, "id": 3, "token": "cc_scim_…", "scimBaseUrl": "https://host/api/scim/v2" }GET /api/org/scim lists token metadata; DELETE /api/org/scim/{id} revokes. GET/POST /api/org/group-mappings lists / upserts a { groupName, role } mapping; DELETE /api/org/group-mappings/{id} clears a group's role.
SCIM 2.0 provisioning (per-org Bearer token)
All /api/scim/v2/* endpoints require Authorization: Bearer <cc_scim_…> and return application/scim+json. Discovery: GET /ServiceProviderConfig, GET /ResourceTypes, GET /Schemas.
/api/scim/v2/UsersSCIM BearerProvision a user (JIT). Role starts at the SCIM default (Viewer) and is elevated by group membership. Duplicate userName → 409 uniqueness.
{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "userName": "alice@corp.example", "name": { "formatted": "Alice A" }, "active": true, "externalId": "0oaExt…" }{ "schemas": ["…:User"], "id": "42", "userName": "alice@corp.example", "active": true, "roles": [{ "value": "Viewer", "primary": true }], "meta": { "resourceType": "User" } }| Status | When |
|---|---|
401 | Missing/invalid/revoked SCIM token (SCIM error envelope). |
409 | A user with that userName already exists (scimType uniqueness). |
/api/scim/v2/Users/{id}SCIM BearerRFC 7644 PatchOp. replace/add of active (active:false deprovisions = deactivate + kill sessions; active:true reactivates), displayName, externalId.
{ "Operations": [{ "op": "replace", "path": "active", "value": false }] }Also: GET /Users?filter=userName eq "x" (and externalId eq), GET /Users/{id}, PUT /Users/{id}, DELETE /Users/{id} (deprovision, 204). Groups: GET/POST /Groups, GET/PATCH/PUT/DELETE /Groups/{id} — PATCH members add/remove applies the group→role mapping to each member.