Create or revise an identity provider connection
Creates or revises a connection document. If the slug does not already exist, a new connection is created. If a connection with that slug already exists, a revision is created.
A revision gets a new revision_id and does not modify the connection
id, so identity links that reference the connection keep resolving while
releases and auth attempts stay pinned to the revision they captured.
Identity fields are fixed for the life of the connection and a revision
that changes one is rejected: protocol, subject_claim, and issuer,
the field that names the authority. Their values decide which provider
account a stored subject belongs to, so changing one would silently
repoint existing identities at a different provider.
subject_claim is optional, and sub is used as the default value. If a
revision updates subject_claim to a different value than the one set
during creation, the request is rejected.
OIDC is the only protocol.
The document is validated against the idp-connection.json schema before
anything is stored. The rules the engine applies when it starts a sign-in
then run on the document, so a connection that could never start one is
refused here instead with idp.endpoints_partial: the OIDC block sets an
endpoint without the others. It either sets no endpoint, and discovery
fills them, or sets authorization_endpoint, token_endpoint, jwks_uri,
and userinfo_endpoint. userinfo_endpoint may be left out when
id_token_mapping is on, but setting it alone still counts as setting an
endpoint. The details list the missing endpoints.
A refused document stores nothing, and on a revise the current revision stays unchanged.
oauth2 idp.writeAuthorizationBearer <token>Scope: idp.write
project_id*stringThe unique identifier of the project
^[a-zA-Z0-9_-]+$application/json- body
Creates or revises an identity provider connection document.
idp*The connection document, in the shape of a .zitadel/idps/<slug>.json
file. If its slug does not already exist, a new connection is created.
If a connection with that slug already exists, this becomes a new
revision of it. The document is validated against the
idp-connection.json schema, and returned as the definition in the
response.
The IdP connection document after revision.
application/json- response
An identity provider connection.
id*stringA unique connection id, generated when the connection is created, and shared by every revision. This id is referenced by the identity links.
revision_id*stringThe id of the revision this row holds, pinned by auth attempts and
releases. GET /idps/{id} and the query return the newest one;
GET /idps/revisions/{revision_id} returns the requested revision.
slug*stringThe identifier by which user schemas and flow definitions reference the connection. Fixed for the life of the connection.
created_at*stringWhen the connection was created.
date-timeupdated_at*stringWhen this revision was created. On the newest revision, that is when the connection was last revised.
date-timedefinition*The stored connection document.
import { createZitadelClient } from "@zitadel/api/client";const client = createZitadelClient({ baseUrl: process.env.ZITADEL_URL ?? "http://localhost:8080", token: process.env.ZITADEL_PROJECT_SECRET!, // server-side only});const idp = await client.createIdp( { idp: { slug: "google", protocol: "oidc", template: "google", display_name: "Google", subject_claim: "sub", claim_mapping: { email: "email", givenName: "given_name", familyName: "family_name", }, verified_claims: { email: "email_verified" }, provisioning: { creation: "auto" }, oidc: { issuer: "https://accounts.google.com", client_id: "${{ GOOGLE_CLIENT_ID }}", client_secret: "${{ GOOGLE_CLIENT_SECRET }}", scopes: ["openid", "profile", "email"], static_authorize_parameters: { prompt: "select_account" }, }, }, }, { project_id: "proj_01KWH1P4MYS7F0N9WD3P2E4YM5" },);The scope list grew. id is the one allocated when the
connection was created, revision_id is new, and updated_at
has moved past created_at.
{ "id": "idp_01KWH3B72K7M7F0N9WD3P2E4YM", "revision_id": "idprev_01KWHF2XY6RN7F0N9WD3P2E4YM", "slug": "google", "created_at": "2026-07-14T09:11:00Z", "updated_at": "2026-07-16T14:20:00Z", "definition": { "slug": "google", "protocol": "oidc", "template": "google", "display_name": "Google", "subject_claim": "sub", "claim_mapping": { "email": "email", "givenName": "given_name", "familyName": "family_name" }, "verified_claims": { "email": "email_verified" }, "provisioning": { "creation": "auto" }, "oidc": { "issuer": "https://accounts.google.com", "id_token_mapping": false, "client_id": "${{ GOOGLE_CLIENT_ID }}", "client_secret": "${{ GOOGLE_CLIENT_SECRET }}", "token_endpoint_auth_method": "client_secret_basic", "scopes": [ "openid", "profile", "email", "https://www.googleapis.com/auth/user.phonenumbers.read" ], "pkce_enabled": true, "static_authorize_parameters": { "prompt": "select_account" } } }}Was this helpful?