---
title: "Save the connection: OpenID Connect (issuer, client id and secret, token method) or SAML 2.0 (the identity provider's metadata), and where new people join."
method: PUT
path: "/v1/organizations/current/sso"
tags: ["organizations"]
---

# Save the connection: OpenID Connect (issuer, client id and secret, token method) or SAML 2.0 (the identity provider's metadata), and where new people join.

`PUT /v1/organizations/current/sso`

## Request

- Base URL: `https://api.50heads.com`
- URL: `https://api.50heads.com/v1/organizations/current/sso`
- Auth: HTTP bearer

Organization admins only (403 `organization_admin_required`), on a browser session with a fresh proof in the `x-50h-reauth` header (401 `reauth_required`). It needs a person: API keys, connected apps and service accounts get 403 `session_required`. Every change is written to the organization's audit. 201 the first time. OIDC (`protocol` left out or `oidc`): the issuer's discovery document is read before saving (400 `sso_discovery_failed`); the secret is required the first time and kept when left out. SAML (`protocol: "saml"`): `metadataUrl` (read now, https on a public host, 6-second timeout, no redirects) or `metadataXml`, one of them; metadata that cannot be read, wants signed requests or has no HTTP-Redirect single sign-on URL is 400 `saml_metadata_invalid`; `allowIdpInitiated` (default false) accepts sign-ins started at the identity provider. A provider change (OIDC issuer, client id, secret or token method; SAML entity ID, single sign-on URL or certificates replaced; or a switch of protocol) needs a new test before people can sign in, and is refused while enforcement is on (409 `sso_enforced`). `defaultRole` is admin, member or viewer, never owner.

## Request body

- union
  - object
    - `protocol` 'oidc'
    - `issuer` string, required
    - `clientId` string, required
    - `clientSecret` string
    - `tokenAuthMethod` 'client_secret_basic' | 'client_secret_post'
    - `defaultWorkspaceId` string, nullable
    - `defaultRole` 'admin' | 'member' | 'viewer'
  - object
    - `protocol` 'saml', required
    - `metadataUrl` string
    - `metadataXml` string
    - `allowIdpInitiated` boolean
    - `defaultWorkspaceId` string, nullable
    - `defaultRole` 'admin' | 'member' | 'viewer'

## Response `200`

OK

- OrganizationSsoGetResponse
  - `connection` object, nullable, required
    - `id` string, required
    - `protocol` 'oidc' | 'saml', required
    - `issuer` string, required: OIDC: the identity provider's issuer URL, exactly as its discovery document gives it. SAML: the identity provider's entity ID.
    - `clientId` string, required
    - `clientSecretSet` boolean, required
    - `clientSecretHint` string, nullable, required
    - `tokenAuthMethod` 'client_secret_basic' | 'client_secret_post', required
    - `defaultWorkspaceId` string, nullable, required
    - `defaultRole` 'admin' | 'member' | 'viewer', required
    - `state` 'draft' | 'tested' | 'enabled', required
    - `enforce` boolean, required
    - `enforceEnabledAt` string, nullable, required
    - `configChangedAt` string, required
    - `lastTest` object, nullable, required
      - `at` string, required
      - `by` object, required
        - `id` string, required
        - `name` string, nullable, required
      - `result` string, required
      - `matchedTester` boolean, required
      - `current` boolean, required
    - `lastSignInAt` string, nullable, required
    - `createdAt` string, required
    - `updatedAt` string, nullable, required
    - `saml` object, nullable, required
      - `idpEntityId` string, required
      - `ssoUrl` string, required
      - `metadataUrl` string, nullable, required
      - `certificates` object[], required
        - `fingerprint` string, required
        - `notBefore` string, required
        - `notAfter` string, required
        - `subject` string, nullable, required
        - `keyType` 'rsa' | 'ec-p256', required
      - `allowIdpInitiated` boolean, required
  - `redirectUri` string, required
  - `scopes` string[], required
  - `saml` object, required
    - `entityId` string, required
    - `acsUrl` string, required
    - `metadataUrl` string, required
    - `nameIdFormat` string, required

## Other responses

- `400`: The request is not valid; `error.details.validation` lists the fixes.
- `401`: No key or token, or it expired or was revoked.
- `403`: The key or token lacks the scope (`insufficient_scope`), or the action is not allowed.
- `429`: Too many requests; wait for Retry-After.

---

[API](https://skmtc.dev/50heads/apis/50heads-api.md) · [All operations](https://skmtc.dev/50heads/apis/50heads-api/llms.txt) · [OpenAPI document](https://skmtc.dev/50heads/apis/50heads-api/revisions/20175e8b00e3?raw)
