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 thesso:managescope: Manage the org's SSO connection, domains, and invitesGranted bywrite_api.Every operation this scope unlocksAudited · 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
provisioningorfailedis retried by saving the connection again. - updated_atstring
- verified_domainsarray of Domain (string)
created_byActorSummary or nulloptional
- The ActorSummary schema
- emailstring
- idstring
- usernamestring
- avatar_urlstring 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
reasonorcode. - fieldstring or nulloptionalOn a
400that 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 oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): 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
reasonorcode. - fieldstring or nulloptionalOn a
400that 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 oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): 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;
reasonnames the permission or the rule that refused it - INSUFFICIENT_SCOPEThe access token lacks the scope this operation needs;
required_scopenames 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
reasonorcode. - fieldstring or nulloptionalOn a
400that 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 oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): 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
reasonorcode. - fieldstring or nulloptionalOn a
400that 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 oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): 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;
reasonsays 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
reasonorcode. - fieldstring or nulloptionalOn a
400that 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 oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): 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
reasonorcode. - fieldstring or nulloptionalOn a
400that 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 oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): 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