Saltar al contenido principal
DocumentaciónIdentidad y acceso · console.latam.ccsio.ai

Single sign-on

An organization's own identity provider connection and the email domains that send its people to it, and the discoveries the login page calls before anyone has signed in.

Menú de la documentación

Las descripciones de las operaciones y los campos son las del contrato, en inglés.

GET/identity/v1/organizations/{org}/sso

Read the organization's single sign-on connection

Credencial
API key
Permiso
sso.manage

Requires sso.manage (the metadata names the identity provider and its client id). Returns the connection's metadata - never a secret. 404 sso-not-configured when the organization has none. Single sign-on is optional per organization and applies to users from Admin downwards; the Root who created the organization keeps password login.

curl
curl "https://console.latam.ccsio.ai/identity/v1/organizations/{org}/sso" \
  -H "Authorization: Bearer $CCSIO_API_KEY"

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

org
obligatorio
pathstring

The organization id (C7 identifier). A value outside the pattern is refused with 400 name-invalid.

Respuestas

  • 200

    The connection.

    Esquema
    SSOConnection
    • providerstringobligatorio

      The identity-provider kind: entra (Microsoft Entra ID, registered in Zitadel through its Azure AD template) or oidc (a generic OIDC provider).

      Valores permitidos: "entra""oidc"

    • display_namestringobligatorio

      The name the connection is shown under (also the provider's name in the identity provider's login page).

      1 to 64 characters

    • issuerstringopcional

      oidc connections only: the OIDC issuer URL (https). Absent for entra.

      at most 200 characters

    • tenant_idstringopcional

      entra connections only: the Entra tenant - a tenant GUID or domain, or one of organizations | common | consumers. Absent for oidc.

      at most 253 characters

    • client_idstringobligatorio

      1 to 200 characters

    • scopesarray of stringobligatorio

      The scopes the identity provider is asked for.

      at most 20 items

    • enabledbooleanobligatorio

      Whether the provider is attached to the organization's login policy. A disabled connection is kept but nobody can sign in through it, and the public discovery answers 404.

    • zitadel_idp_idstringobligatorio

      The id of the organization-level identity provider inside the organization's linked Zitadel organization.

    • redirect_uristring (uri)obligatorio

      The redirect URI the customer must register at their identity provider (for Entra: the app registration's Web redirect URI).

    • created_atstring (date-time)obligatorio
    • updated_atstring (date-time)obligatorio
  • 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:

    Leer más

    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

  • 402

    The organization has to pay first: its standing is payment_required.

    Leer más

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 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.

    Leer más

    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.

  • 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)

PUT/identity/v1/organizations/{org}/sso

Create or update the organization's single sign-on connection

Credencial
API key
Permiso
sso.manage
Cuerpo de la solicitud
Cuerpo de hasta 1 MiB

Requires sso.manage (a role permission held by root and organization_admin, assignable to custom roles).

Leer más

Registers (or updates) an ORGANIZATION-level identity provider - Microsoft Entra ID through Zitadel's Azure AD template, or a generic OIDC provider - in the organization's linked Zitadel organization, makes sure its login policy allows external identity providers, and attaches or detaches the provider according to enabled. 201 when the connection was created, 200 when it was updated; the body is the connection (without the secret). client_secret is write-only: required to create and to change provider (400 sso-secret-required), optional on update. At most one connection per organization. Users who sign in through it are created automatically in the organization's Zitadel organization and, on their first sign-in, provisioned into the organization with the role user (no group or claim mapping). Refused for a deleted organization (409 organization-deleted); an organization without a linked Zitadel organization is 409 sso-organization-unlinked. An organization's alias exists only while its connection is enabled: an update that leaves the connection disabled releases the alias in the same transaction, and the organization.updated security event records it (details alias_from). Sensitive: audited, and records an sso.configured (201) or sso.updated (200) security event.

curl
curl -X PUT "https://console.latam.ccsio.ai/identity/v1/organizations/{org}/sso" \
  -H "Authorization: Bearer $CCSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "provider": "oidc",
  "display_name": "Acme SSO",
  "issuer": "https://idp.example.com",
  "client_id": "ccsio-acme",
  "client_secret": "replace-with-your-client-secret",
  "scopes": [
    "openid",
    "profile",
    "email"
  ],
  "enabled": true
}'

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

org
obligatorio
pathstring

The organization id (C7 identifier). A value outside the pattern is refused with 400 name-invalid.

Cuerpo de la solicitud application/json

PutSSORequest
  • providerstringobligatorio

    The identity-provider kind: entra (Microsoft Entra ID, registered in Zitadel through its Azure AD template) or oidc (a generic OIDC provider).

    Valores permitidos: "entra""oidc"

  • display_namestringobligatorio

    1 to 64 characters

  • issuerstringopcional

    Required for oidc, refused for entra. An https URL without credentials, query or fragment.

    at most 200 characters

  • tenant_idstringopcional

    Required for entra, refused for oidc: a tenant GUID or domain, or organizations | common | consumers.

    at most 253 characters

  • client_idstringobligatorio

    1 to 200 characters

  • client_secretstringopcional

    The client secret issued by the identity provider. Never stored, logged or returned by core.

    1 to 200 characters

  • scopesarray of stringopcional

    Optional; defaults to openid, profile, email (and User.Read for entra, which Zitadel needs to read the user's name from Microsoft Graph).

    at most 20 items

  • enabledbooleanopcional

    Optional; true when the connection is created, unchanged on update.

Respuestas

  • 200

    The connection was updated.

    Esquema
    SSOConnection
    • providerstringobligatorio

      The identity-provider kind: entra (Microsoft Entra ID, registered in Zitadel through its Azure AD template) or oidc (a generic OIDC provider).

      Valores permitidos: "entra""oidc"

    • display_namestringobligatorio

      The name the connection is shown under (also the provider's name in the identity provider's login page).

      1 to 64 characters

    • issuerstringopcional

      oidc connections only: the OIDC issuer URL (https). Absent for entra.

      at most 200 characters

    • tenant_idstringopcional

      entra connections only: the Entra tenant - a tenant GUID or domain, or one of organizations | common | consumers. Absent for oidc.

      at most 253 characters

    • client_idstringobligatorio

      1 to 200 characters

    • scopesarray of stringobligatorio

      The scopes the identity provider is asked for.

      at most 20 items

    • enabledbooleanobligatorio

      Whether the provider is attached to the organization's login policy. A disabled connection is kept but nobody can sign in through it, and the public discovery answers 404.

    • zitadel_idp_idstringobligatorio

      The id of the organization-level identity provider inside the organization's linked Zitadel organization.

    • redirect_uristring (uri)obligatorio

      The redirect URI the customer must register at their identity provider (for Entra: the app registration's Web redirect URI).

    • created_atstring (date-time)obligatorio
    • updated_atstring (date-time)obligatorio
  • 201

    The connection was created.

    Esquema
    SSOConnection
    • providerstringobligatorio

      The identity-provider kind: entra (Microsoft Entra ID, registered in Zitadel through its Azure AD template) or oidc (a generic OIDC provider).

      Valores permitidos: "entra""oidc"

    • display_namestringobligatorio

      The name the connection is shown under (also the provider's name in the identity provider's login page).

      1 to 64 characters

    • issuerstringopcional

      oidc connections only: the OIDC issuer URL (https). Absent for entra.

      at most 200 characters

    • tenant_idstringopcional

      entra connections only: the Entra tenant - a tenant GUID or domain, or one of organizations | common | consumers. Absent for oidc.

      at most 253 characters

    • client_idstringobligatorio

      1 to 200 characters

    • scopesarray of stringobligatorio

      The scopes the identity provider is asked for.

      at most 20 items

    • enabledbooleanobligatorio

      Whether the provider is attached to the organization's login policy. A disabled connection is kept but nobody can sign in through it, and the public discovery answers 404.

    • zitadel_idp_idstringobligatorio

      The id of the organization-level identity provider inside the organization's linked Zitadel organization.

    • redirect_uristring (uri)obligatorio

      The redirect URI the customer must register at their identity provider (for Entra: the app registration's Web redirect URI).

    • created_atstring (date-time)obligatorio
    • updated_atstring (date-time)obligatorio
  • 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:

    Leer más

    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

  • 402

    The organization has to pay first: its standing is payment_required.

    Leer más

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 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.

    Leer más

    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.

  • 409

    The request conflicts with the current state of the resource or with an invariant it protects (a taken name, a role still in use, an organization that must not be deleted, an archived team, the last active root, a seat or service account limit).

  • 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)

Respuesta de ejemplo
{
  "provider": "oidc",
  "display_name": "Acme SSO",
  "issuer": "https://idp.example.com",
  "client_id": "ccsio-acme",
  "scopes": [
    "openid",
    "profile",
    "email"
  ],
  "enabled": true,
  "zitadel_idp_id": "298437125649084512",
  "redirect_uri": "https://login.example.com/idps/callback",
  "created_at": "2026-10-14T10:05:00Z",
  "updated_at": "2026-10-14T10:05:00Z"
}
DELETE/identity/v1/organizations/{org}/sso

Remove the organization's single sign-on connection

Credencial
API key
Permiso
sso.manage

Requires sso.manage. Detaches the identity provider from the organization's login policy and deletes it at Zitadel (which also removes its users' links to it), then removes the metadata.

Leer más

Members that were provisioned keep their membership; they can no longer sign in through the removed provider. 404 sso-not-configured when there is none. The organization's alias, which exists only with an enabled connection, is released in the same transaction (it reads null again) and an organization.updated security event records it (details alias_from). Sensitive: audited, and records an sso.removed security event.

curl
curl -X DELETE "https://console.latam.ccsio.ai/identity/v1/organizations/{org}/sso" \
  -H "Authorization: Bearer $CCSIO_API_KEY"

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

org
obligatorio
pathstring

The organization id (C7 identifier). A value outside the pattern is refused with 400 name-invalid.

Respuestas

  • 204

    The connection was removed.

  • 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:

    Leer más

    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

  • 402

    The organization has to pay first: its standing is payment_required.

    Leer más

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 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.

    Leer más

    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.

  • 409

    The request conflicts with the current state of the resource or with an invariant it protects (a taken name, a role still in use, an organization that must not be deleted, an archived team, the last active root, a seat or service account limit).

  • 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)

GET/identity/v1/sso/discovery

Discover an organization's single sign-on (public)

Credencial
Ninguna: una operación pública
Permiso
Ninguno además de la credencial

PUBLIC: no credential, because the portal's "Continue with SSO" asks it before anyone has signed in.

Leer más

Returns the identifiers the portal needs to start the normal OIDC login against Zitadel restricted to the organization: the organization's Zitadel id (scope urn:zitadel:iam:org:id:<zitadel_org_id>), its primary domain (scope urn:zitadel:iam:org:domain:primary:<zitadel_org_domain>, which Login V2 needs to find a custom-id organization) and its identity provider (scope urn:zitadel:iam:org:idp:id:<idp_id>). Answers 404 not-found for an unknown, deleted or suspended organization, for one without a connection, for one whose connection is disabled and for a malformed id - indistinguishably, so it reveals nothing about which. 400 invalid-request when organization is missing; 429 rate-limited past a per-client budget (Retry-After). Read-only, never cached (Cache-Control: no-store). The organization parameter is the organization id or its alias (an organization id wins when both would match); the answer's organization is always the organization id. Email-domain discovery is POST /identity/v1/login/discovery.

curl
curl "https://console.latam.ccsio.ai/identity/v1/sso/discovery?organization=<organization>"

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

organization
obligatorio
querystring

The organization id (slug) or the organization's alias, as the user typed it.

Respuestas

  • 200

    An enabled connection exists.

    Esquema
    SSODiscovery
    • organizationstringobligatorio

      The id of the organization the lookup resolved to (an organization id, also when the lookup was by alias).

      pattern ^[a-z][a-z0-9._-]{0,63}$

    • zitadel_org_idstringobligatorio

      The organization's linked Zitadel organization: send urn:zitadel:iam:org:id:<zitadel_org_id> as an OIDC scope.

      at least 1 characters

    • zitadel_org_domainstringobligatorio

      The primary domain of that Zitadel organization: send urn:zitadel:iam:org:domain:primary:<zitadel_org_domain> as an OIDC scope too. Zitadel's Login V2 reads the org id scope only for numeric ids, while core's organizations carry custom ones (cp-<ulid>); the domain scope is what tells the login screen which organization is meant.

      at least 1 characters

    • idp_idstringobligatorio

      The organization's identity provider in Zitadel: urn:zitadel:iam:org:idp:id:<idp_id> as an OIDC scope is the hint that skips the provider chooser.

      at least 1 characters

  • 400

    Client refusal unrelated to authentication, including malformed input, a denied or failed request.

  • 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.

  • 429

    The caller used up a budget. `Retry-After` says how many seconds to wait. `error.code` says which budget. Codes: rate-limited (the per-client budget of the public discovery routes), registration-rate-limited (sign-up), support-session-limit (an operator's open support sessions)

  • 500

    Platform failure, rendered without internal cause details.

GET/identity/v1/organizations/{org}/sso/domains

List the organization's single sign-on email domains

Credencial
API key
Permiso
sso.manage

Requires sso.manage. The domains the organization has added, pending and verified, oldest first. A pending domain carries the TXT record to publish.

curl
curl "https://console.latam.ccsio.ai/identity/v1/organizations/{org}/sso/domains" \
  -H "Authorization: Bearer $CCSIO_API_KEY"

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

org
obligatorio
pathstring

The organization id (C7 identifier). A value outside the pattern is refused with 400 name-invalid.

Respuestas

  • 200

    The domains.

    Esquema
    ListSSODomainsResponse
    • domainsarray of SSODomainobligatorio
      • domainstringobligatorio

        at most 253 characters

      • statusstringobligatorio

        pending: added, the TXT record not yet confirmed. verified: the TXT record matched; the organization now owns the domain for email discovery.

        Valores permitidos: "pending""verified"

      • txt_recordSSODomainTXTRecord or nullobligatorio

        The record to publish while the domain is pending; null once it is verified.

      • created_atstring (date-time)obligatorio
      • verified_atstring (date-time) or nullobligatorio

        null while pending.

  • 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:

    Leer más

    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

  • 402

    The organization has to pay first: its standing is payment_required.

    Leer más

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 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.

    Leer más

    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.

  • 409

    The request conflicts with the current state of the resource or with an invariant it protects (a taken name, a role still in use, an organization that must not be deleted, an archived team, the last active root, a seat or service account limit).

  • 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)

POST/identity/v1/organizations/{org}/sso/domains

Add an email domain to the organization's single sign-on

Credencial
API key
Permiso
sso.manage
Cuerpo de la solicitud
Cuerpo de hasta 1 MiB

Requires sso.manage. Adds the domain as pending and returns the DNS TXT record to publish (name _ccsio-verification.<domain>, value ccsio-verification=<token>, the token 32 random letters and digits). Nothing is checked yet: publish the record, then call verify.

Leer más

Refused when the organization already holds the domain (409 sso-domain-exists), when another organization has already VERIFIED it (409 sso-domain-taken) and past 20 domains (409 sso-domain-limit); a domain outside the shape (lowercase ASCII hostname, at least one dot, at most 253 characters, no trailing dot, not an IP address) is 400 sso-domain-invalid. Sensitive: audited, and records an sso.domain_added security event.

curl
curl -X POST "https://console.latam.ccsio.ai/identity/v1/organizations/{org}/sso/domains" \
  -H "Authorization: Bearer $CCSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "domain": "string"
}'
Construido con los campos obligatorios del esquema: reemplaza los valores.

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

org
obligatorio
pathstring

The organization id (C7 identifier). A value outside the pattern is refused with 400 name-invalid.

Cuerpo de la solicitud application/json

AddSSODomainRequest
  • domainstringobligatorio

    The email domain, e.g. acme.example (not an email address, not a URL).

    3 to 253 characters

Respuestas

  • 201

    The domain was added, pending.

    Esquema
    SSODomain
    • domainstringobligatorio

      at most 253 characters

    • statusstringobligatorio

      pending: added, the TXT record not yet confirmed. verified: the TXT record matched; the organization now owns the domain for email discovery.

      Valores permitidos: "pending""verified"

    • txt_recordobject or nullobligatorio

      The record to publish while the domain is pending; null once it is verified.

      • namestringobligatorio

        The record name: _ccsio-verification.<domain>.

        at most 253 characters

      • valuestringobligatorio

        The record value: ccsio-verification=<token>, the token being 32 random letters and digits.

        pattern ^ccsio-verification=[A-Za-z0-9]{32}$

    • created_atstring (date-time)obligatorio
    • verified_atstring (date-time) or nullobligatorio

      null while pending.

  • 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:

    Leer más

    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

  • 402

    The organization has to pay first: its standing is payment_required.

    Leer más

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 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.

    Leer más

    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.

  • 409

    The request conflicts with the current state of the resource or with an invariant it protects (a taken name, a role still in use, an organization that must not be deleted, an archived team, the last active root, a seat or service account limit).

  • 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)

POST/identity/v1/organizations/{org}/sso/domains/{domain}/verify

Verify an email domain by its DNS TXT record

Credencial
API key
Permiso
sso.manage

Requires sso.manage. Looks the domain's TXT record up in DNS (name _ccsio-verification.<domain>) and marks the domain verified only when one of the record's values is exactly ccsio-verification=<token>.

Leer más

A verified domain makes email discovery send the domain's users to the organization's identity provider, when its connection is enabled. A domain can be verified by at most one organization (409 sso-domain-taken for the loser of a race, or when it was already verified elsewhere). When the record is missing, the domain does not exist in DNS or no value matches the answer is 409 sso-domain-verification-failed (publish the record and retry); when DNS could not be asked (timeout, server failure) it is 503 sso-domain-dns-unavailable (retry later). A domain this organization already verified is returned as is (200). Sensitive: audited, and records an sso.domain_verified security event.

curl
curl -X POST "https://console.latam.ccsio.ai/identity/v1/organizations/{org}/sso/domains/{domain}/verify" \
  -H "Authorization: Bearer $CCSIO_API_KEY"

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

org
obligatorio
pathstring

The organization id (C7 identifier). A value outside the pattern is refused with 400 name-invalid.

domain
obligatorio
pathstring

The email domain (lowercase ASCII hostname, at least one dot, at most 253 characters, no trailing dot, not an IP address). Upper case is folded to lower case; anything else outside the shape is refused with 400 sso-domain-invalid.

Respuestas

  • 200

    The domain is verified.

    Esquema
    SSODomain
    • domainstringobligatorio

      at most 253 characters

    • statusstringobligatorio

      pending: added, the TXT record not yet confirmed. verified: the TXT record matched; the organization now owns the domain for email discovery.

      Valores permitidos: "pending""verified"

    • txt_recordobject or nullobligatorio

      The record to publish while the domain is pending; null once it is verified.

      • namestringobligatorio

        The record name: _ccsio-verification.<domain>.

        at most 253 characters

      • valuestringobligatorio

        The record value: ccsio-verification=<token>, the token being 32 random letters and digits.

        pattern ^ccsio-verification=[A-Za-z0-9]{32}$

    • created_atstring (date-time)obligatorio
    • verified_atstring (date-time) or nullobligatorio

      null while pending.

  • 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:

    Leer más

    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

  • 402

    The organization has to pay first: its standing is payment_required.

    Leer más

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 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.

    Leer más

    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.

  • 409

    The request conflicts with the current state of the resource or with an invariant it protects (a taken name, a role still in use, an organization that must not be deleted, an archived team, the last active root, a seat or service account limit).

  • 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)

DELETE/identity/v1/organizations/{org}/sso/domains/{domain}

Remove an email domain from the organization's single sign-on

Credencial
API key
Permiso
sso.manage

Requires sso.manage. Removes the domain, pending or verified; a verified domain stops routing its users to the organization's identity provider at once. 404 sso-domain-not-found when the organization does not hold it. Sensitive: audited, and records an sso.domain_removed security event.

curl
curl -X DELETE "https://console.latam.ccsio.ai/identity/v1/organizations/{org}/sso/domains/{domain}" \
  -H "Authorization: Bearer $CCSIO_API_KEY"

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

org
obligatorio
pathstring

The organization id (C7 identifier). A value outside the pattern is refused with 400 name-invalid.

domain
obligatorio
pathstring

The email domain (lowercase ASCII hostname, at least one dot, at most 253 characters, no trailing dot, not an IP address). Upper case is folded to lower case; anything else outside the shape is refused with 400 sso-domain-invalid.

Respuestas

  • 204

    The domain was removed.

  • 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:

    Leer más

    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

  • 402

    The organization has to pay first: its standing is payment_required.

    Leer más

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 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.

    Leer más

    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.

  • 409

    The request conflicts with the current state of the resource or with an invariant it protects (a taken name, a role still in use, an organization that must not be deleted, an archived team, the last active root, a seat or service account limit).

  • 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)

POST/identity/v1/login/discovery

Discover how a user signs in (public)

Credencial
Ninguna: una operación pública
Permiso
Ninguno además de la credencial
Cuerpo de la solicitud
Cuerpo de hasta 4096 bytes

PUBLIC: no credential, because the portal's login asks it before anyone has signed in. The body is exactly one of {"email"} and {"alias"}.

Leer más

By alias: method sso (an active organization with an ENABLED connection) with the alias, zitadel_org_id, zitadel_org_domain and idp_id; every other alias - unknown, deleted or suspended, without a linked Zitadel organization, or belonging to an organization WITHOUT an enabled connection - is the same 404 not-found, indistinguishably. An alias exists only for an organization with single sign-on, and a plain login restricted to an organization cannot work (the identity provider appends the organization's primary domain to the login name), so there is no method password answer for an alias. By email: only the address's domain is read; when an organization has VERIFIED that domain and has an enabled connection the answer is method sso with the same fields, in every other case - unknown domain, pending or unverified domain, disabled or missing connection - it is exactly {"method":"password"}. No user is looked up, so the answer never depends on whether the account exists. 400 invalid-request when the body is not exactly one well-formed email or alias; 413 past 4096 bytes; 429 rate-limited past a per-client budget (Retry-After), shared with GET /identity/v1/sso/discovery. Never cached (Cache-Control: no-store).

curl
curl -X POST "https://console.latam.ccsio.ai/identity/v1/login/discovery" \
  -H "Content-Type: application/json" \
  -d 'null'
Construido con los campos obligatorios del esquema: reemplaza los valores.

Parámetros

NombreEnDescripción
X-Request-ID
opcional
headerstring

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.

Cuerpo de la solicitud application/json

LoginDiscoveryRequest

Exactly one of email and alias. The email travels in the body, never in a URL, and core never logs it. Naming both, neither, or an empty value is refused with 400 invalid-request.

Uno de

  • #1anyopcional
  • #2anyopcional

Respuestas

  • 200

    How to sign in.

    Esquema
    LoginDiscovery
    • methodstringobligatorio

      sso: the organization's own identity provider. password: the normal Zitadel login (a lookup by email only).

      Valores permitidos: "sso""password"

    • aliasstringopcional

      An organization's alias: the public name its sign-in link is built from (https://<console>/<alias>). 3 to 63 lowercase letters, digits and hyphens, starting and ending with a letter or digit. Unique across the plane and editable by the organization's Root and Admin; the organization's internal id never changes. An alias exists only for an organization with an ENABLED single sign-on connection: setting or changing one without it is refused with 409 alias-requires-sso, and removing or disabling the connection releases the alias (it reads null again). Reserved words (every top-level console path - api, auth, login, logout, register, onboarding, organizations, identity, audit, models, deployments, playground, settings, request-logs, metering, memory, registrars, usage - and common words such as admin, help, docs, static, assets, health, ready, www, console, app) and anything shaped like a generated organization id (org-<26 characters>) are refused with 400 alias-reserved; a malformed one with 400 alias-invalid; one already in use with 409 alias-taken.

      3 to 63 characters · pattern ^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])$

    • zitadel_org_idstringopcional

      The organization's linked Zitadel organization: send urn:zitadel:iam:org:id:<zitadel_org_id> as an OIDC scope.

      at least 1 characters

    • zitadel_org_domainstringopcional

      The primary domain of that Zitadel organization: send urn:zitadel:iam:org:domain:primary:<zitadel_org_domain> as an OIDC scope too (Login V2 finds a custom-id organization by it).

      at least 1 characters

    • idp_idstringopcional

      method sso only: the organization's identity provider in Zitadel; urn:zitadel:iam:org:idp:id:<idp_id> is the hint that skips the provider chooser.

      at least 1 characters

  • 400

    Client refusal unrelated to authentication, including malformed input, a denied or failed request.

  • 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.

  • 413

    The body exceeds 4096 bytes. Codes: request-body-too-large

  • 429

    The caller used up a budget. `Retry-After` says how many seconds to wait. `error.code` says which budget. Codes: rate-limited (the per-client budget of the public discovery routes), registration-rate-limited (sign-up), support-session-limit (an operator's open support sessions)

  • 500

    Platform failure, rendered without internal cause details.

Generado a partir de los contratos de la plataforma en el commit 5f833620.

Explora la plataforma

Obtén tu primera key API

El registro está abierto. Cuatro pasos hasta tu primera llamada: crea tu cuenta, crea tu organización, crea tu API key y empieza a usarla.

  1. 01Crea tu cuenta
  2. 02Crea tu organización
  3. 03Crea tu API key
  4. 04Empieza a usarla