Update user by ID
Partially updates a user's schema-defined attributes, and optionally moves the user to another registered schema. The merged result is validated against the schema before commit. Concurrent writes are last-write-wins.
AuthorizationBearer <token>Scope: user.write
user_id*stringThe unique identifier of the user.
^user_[a-zA-Z0-9_-]+$The changes to merge into the user.
application/json- body
A partial update, merged into the user's current state. At least one of
schema and attributes must be present; an empty patch is rejected with
user.invalid.
attributes is merged key by key into the stored attributes: an omitted
key stays untouched, an object merges recursively, null deletes the
attribute, and any other value replaces the stored one. The merged result
is validated as a whole against the user's schema, so a patch that deletes
or invalidates a required property is rejected with req.invalid.
schema moves the user to another registered schema — the ADR 009 §4
upgrade mechanism. The target must be a revision of the user's current
schema (the same objectType), newer or older; a schema of another
objectType is rejected with user.invalid. A schema stored without an
objectType is a revision of nothing, so a user cannot move to or from
one. The request must be
self-contained: merged attributes are validated against the new schema
before commit, and every uniqueness claim is recomputed under the new
schema's annotations. Values removed by an earlier move are not restored
by moving back.
1 <= propertiesschema?stringThe schema the user follows after this patch. Omit it to keep the
current schema. The schema must already be registered via /schemas
and be a revision of the user's current schema.
1 <= lengthattributes?The changed attributes only. null deletes an attribute; omitted
keys are untouched.
1 <= propertiesUpdated user state.
application/json- response
A user represents an individual identity in the system. It can be used to represent a human user, but also a service account or any other type of identity.
attributes is the document that satisfies the user schema named by
schema: its property names and types are defined entirely by that schema,
and it is what the schema validates. The rest of the object — id,
schema, metadata — is the server-owned envelope. Keeping the two apart
means a schema may name a property id or metadata without colliding with
the envelope, and closed-world keywords (additionalProperties: false,
propertyNames, unevaluatedProperties) behave as their author expects.
id*user-id^user_[a-zA-Z0-9_-]+$schema*stringThe schema that defines the content of attributes. These schemas can be
created using the /schemas endpoint. A default schema is provided.
This schema can be retrieved using the same endpoint.
attributes*The user's content, satisfying the schema named by schema. Property
names and types are determined entirely by that schema.
metadata*identifier?stringThe current value of the user schema's designated identifier
(x-identifier), resolved live at read time. Absent when the schema
designates no identifier or the user carries no value for it.
identifier_property?stringThe schema property identifier came from, so clients can reach the
property's schema for semantics (a mailto link, a field label)
instead of guessing from the value. Present exactly when
identifier is.
display?stringThe x-display rendering — the designated properties' values joined
in list order, resolved live at read time. Purely presentational.
Absent when the schema designates no display properties or the user
carries no values for them. Clients render display, falling back
to identifier, then id.
teams?array<>The user's team memberships, present only when the request asked for them with
expand: ["teams"] (ADR 059). Absent means it was not requested; []
means the user has none.
Deliberately outside metadata: memberships are a related collection, not
part of the server-owned envelope, and it is a different concept from
metadata.lifecycle_owner_team_id (ADR 024).
teams_truncated?booleanTrue when the user is on more teams than the embedded list carries. The
embedded list is capped and cannot be paged; read them all at
GET /users/{user_id}/teams. Present only alongside teams.
import { configureZitadel, getApi } from "@zitadel/api/config";import { setApiCsrfToken } from "@zitadel/api/runtime/auth";// In the browser, through the SDK proxy: the session cookie authenticates the call.const client = getApi(configureZitadel({ projectId: "proj_01KWH1P4MYS7F0N9WD3P2E4YM5" }));// A write the session cookie authenticates carries the session's CSRF token.setApiCsrfToken((await client.getMySessionCsrfToken()).csrf_token);const user = await client.patchUserByID("user_01KWH3B72K7M7F0N9WD3P2E4YM", {});{ "id": "string", "schema": "string", "attributes": {}, "metadata": { "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "status": "active", "lifecycle_owner_team_id": "string", "lifecycle_owner_team": { "id": "string", "name": "string", "status": "active", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } }, "identifier": "string", "identifier_property": "string", "display": "string", "teams": [ { "id": "string", "name": "string", "membership_status": "pending", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } ], "teams_truncated": true}Was this helpful?