Skip to content
GitmoapAPIBeta
Identity & platformsso
PUT/groups/{group_id}/sso-connection

Create or replace the organization's single sign-on connection.

put_sso_connection
  • sso:manage
    A token needs the sso:manage scope: Manage the org's SSO connection, domains, and invitesGranted by write_api.Every operation this scope unlocks
  • Audited · mutation

    x-gitmoap-audit: {"kind":"audited","arg":"mutation"}

Only the organization's owners configure it, on its top-level group. The body names one protocol — SAML 2.0 (a metadata URL or document) or OpenID Connect (issuer, client id and secret) — with the attribute mapping, whether newcomers on verified domains get an account at their first sign-in, whether sign-in through the provider is enforced, and the role newcomers receive (Reporter by default). The provider is set up straight away and the response says whether that worked (active) or not (failed, with the error); a change made while another is still being set up is refused.

Parameters

Path
  • group_idGroupId (string · uuid)The organization's top-level group

Request body

application/json
  • protocolSsoProtocolsamloidcThe IdP protocol an org's connection speaks.
  • attribute_mappingSsoAttributeMapping or nulloptional
    • The SsoAttributeMapping schema
    • emailstringThe claim or attribute carrying the person's email address. Defaults to email.
    • groupsstring or nulloptionalThe claim listing the person's groups at the identity provider, if any. Teams linked to those groups follow it.
    • usernamestring or nulloptionalThe claim a new account's username is derived from, if any.
  • auto_provisionbooleanoptionalWhether to create an account for a person from a verified domain the first time they sign in. Defaults to false.
  • default_roleRoleRef or nulloptionalThe role newcomers are given at the top-level group — a built-in role, or one of the organization's own (default Reporter). Invites without a role of their own use it too.
  • enforcedbooleanoptionalWhether people from a verified domain must sign in through SSO. Defaults to false.
  • idp_sync_max_age_daysinteger · int32 or nulloptional0–∞Days, 1–365, a person's place on a team linked to an identity-provider group lasts without them signing in again to confirm it (default 30).
  • oidcOidcConfigRequest or nulloptional
    • The OidcConfigRequest schema
    • client_idstring or nulloptional
    • client_secretstring or nulloptionalThe client secret. Write-only: it is stored encrypted and never returned.
    • issuer_urlstring or nulloptionalThe OIDC issuer URL. Its settings are discovered from /.well-known/openid-configuration.
    • scopesarray of string or nulloptionalThe scopes to request. Defaults to ["openid", "email", "profile"].
  • samlSamlConfigRequest or nulloptional
    • The SamlConfigRequest schema
    • metadata_urlstring or nulloptionalThe URL of the identity provider's SAML metadata, which is fetched and refreshed from there. Give this or metadata_xml.
    • metadata_xmlstring or nulloptionalThe identity provider's SAML metadata document itself, as XML. Give this or metadata_url.
Request body exampleSynthesized example
{
"protocol": "saml"
}

Responses

200application/json
  • attribute_mappingSsoAttributeMapping
    • The SsoAttributeMapping schema
    • emailstringThe claim or attribute carrying the person's email address. Defaults to email.
    • groupsstring or nulloptionalThe claim listing the person's groups at the identity provider, if any. Teams linked to those groups follow it.
    • usernamestring or nulloptionalThe claim a new account's username is derived from, if any.
  • auto_provisionboolean
  • cognito_idp_nameSsoIdpName (string)The name the identity provider is registered under for sign-in.
  • created_atstring
  • default_roleRoleViewThe role newcomers are given at the top-level group.
    • The RoleView schema
    • namestringThe role's display name: a built-in name such as Developer, or the custom role's name.
    • rankAccessLevelguestreporterdevelopermaintainerownerThe built-in rank the role counts as wherever a rank is compared, such as a protected branch's minimum.
    • builtinAccessLevelguestreporterdevelopermaintainerowneror nulloptionalSet when the role is built in.
    • customRoleId (string · uuid) or nulloptionalSet when the role is one the organization defined.
  • enforcedboolean
  • idp_sync_max_age_daysinteger · int320–∞Days a place on a team linked to an identity-provider group lasts without the person signing in again.
  • protocolSsoProtocolsamloidcThe IdP protocol an org's connection speaks.
  • root_group_idGroupId (string · uuid)
  • statusSsoConnectionStatuspendingprovisioningactivefaileddisabledWhere an organization's SSO connection is in being set up. A connection left provisioning or failed is retried by saving the connection again.
  • updated_atstring
  • verified_domainsarray of Domain (string)
  • created_byActorSummary or nulloptional
  • last_provision_errorstring or nulloptional
  • oidcOidcConfigView or nulloptional
    • The OidcConfigView schema
    • client_secret_setboolean
    • scopesarray of string
    • client_idstring or nulloptional
    • issuer_urlstring or nulloptional
  • samlSamlConfigView or nulloptional
    • The SamlConfigView schema
    • metadata_xml_setbooleanWhether a SAML metadata document was supplied directly rather than by URL.
    • metadata_urlstring or nulloptional
200 exampleSynthesized example
{
"attribute_mapping": {
"email": "mara@acme.example",
"groups": "groups-dab4",
"username": "tomas"
},
"auto_provision": false,
"cognito_idp_name": "payments-api",
"created_at": "2026-10-14T15:39:59Z",
"default_role": {
"name": "payments-api",
"rank": "guest",
"builtin": "guest",
"custom": "f38accd1-84c7-463a-88eb-244087abb0d0"
},
"enforced": false,
"idp_sync_max_age_days": 70,
"protocol": "saml",
"root_group_id": "4c1d8e2f-6a3b-4f90-b7c5-1e2d3c4b5a69",
"status": "active",
"updated_at": "2026-10-08T16:08:49Z",
"verified_domains": [
"verified-domains-7b83",
"verified-domains-dc8d"
],
"created_by": {
"email": "lin@acme.example",
"id": "id-a216",
"username": "lin",
"avatar_url": "https://gitmoap.example/acme/4fd1d910"
},
"last_provision_error": "last-provision-error-3e4c",
"oidc": {
"client_secret_set": false,
"scopes": [
"scopes-23fd"
],
"client_id": "8d04d8c4-a233-45f0-9f77-e0debf553a6c",
"issuer_url": "https://gitmoap.example/acme/dbe13144"
},
"saml": {
"metadata_xml_set": false,
"metadata_url": "https://gitmoap.example/acme/8dc37a10"
}
}
400application/json
Error codes
  • BAD_REQUESTThe request is malformed: a parameter or a body field is not a well-formed value of its type
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
400 exampleSynthesized example
{
"error": {
"code": "code-365d",
"message": "Stream pipeline status into the run header"
}
}
401application/json
Error codes
  • UNAUTHORIZEDNo credential was sent, or the one sent is invalid, expired or revoked
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
401 exampleSynthesized example
{
"error": {
"code": "code-3ee7",
"message": "Inline scalar newtypes but keep their brand"
}
}
403application/json
Error codes
  • FORBIDDENYou are signed in but may not do this here; reason names the permission or the rule that refused it
  • INSUFFICIENT_SCOPEThe access token lacks the scope this operation needs; required_scope names it
  • PERMISSION_REQUIREDYou need a permission you do not hold here; the message names it
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
403 exampleSynthesized example
{
"error": {
"code": "code-e7ba",
"message": "Stream pipeline status into the run header"
}
}
404application/json
Error codes
  • NOT_FOUNDThe resource does not exist — or exists and you cannot see it: a private resource you have no access to answers exactly as an absent one does
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
404 exampleSynthesized example
{
"error": {
"code": "code-7016",
"message": "Stream pipeline status into the run header"
}
}
409application/json
Error codes
  • CONFLICTThe request conflicts with the resource's current state; reason says how
  • LEGAL_ACCEPTANCE_REQUIREDAccept the current Terms of Service before changing anything; reading stays open
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
409 exampleSynthesized example
{
"error": {
"code": "code-0220",
"message": "Draw the region map from operation density"
}
}
501SSO is not configured on this deploymentapplication/json
Error codes
  • NOT_IMPLEMENTEDThis deployment has not configured the feature the operation needs; the message names it
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
501 exampleSynthesized example
{
"error": {
"code": "code-61f2",
"message": "Pin a page's payload to the build that rendered it"
}
}

CLI

gitmoap sso put-sso-connection

  • --group-ididThe organization's top-level group (id or group path)
  • --attribute-mappingjsonoptional
  • --auto-provisionflagoptionalWhether to create an account for a person from a verified domain the first time they sign in. Defaults to `false`.
  • --default-rolejsonoptional
  • --enforcedflagoptionalWhether people from a verified domain must sign in through SSO. Defaults to `false`.
  • --idp-sync-max-age-daysnumberoptionalDays, 1–365, a person's place on a team linked to an identity-provider group lasts without them signing in again to confirm it (default 30).
  • --oidcjsonoptional
  • --protocolsaml | oidc
  • --samljsonoptional

Used in these guides