Skip to content
Torii docs

Update user metadata

PATCH
/api/server/v1/users/{userId}/metadata
curl --request PATCH \
--url https://api.torii.so/api/server/v1/users/01931a73-8b00-7000-8000-000000000000/metadata \
--header 'Content-Type: application/json' \
--data '{ "publicMetadata": { "plan": "pro" }, "privateMetadata": { "stripeId": "cus_123" }, "unsafeMetadata": { "onboardingStep": 2 } }'

Deep-merges into any of the three metadata bags. Each bag is tri-state: omit the key to leave the bag unchanged, or send an object to deep-merge into the existing bag (a key set to null removes it). The merged result is capped at 512 bytes for publicMetadata/unsafeMetadata and 4096 bytes for privateMetadata.

userId
required
string format: uuid

Identifier of the user to update.

Example
01931a73-8b00-7000-8000-000000000000
Media type application/json

PATCH body for a user’s metadata bags. Each bag is tri-state: omit to leave it unchanged, or send an object value. Whether the object merges into or replaces the bag depends on the endpoint (see its operation description).

object
publicMetadata

Public metadata bag: SDK-readable, server-written. Max 512 bytes.

object
key
additional properties
any
Example
{
"plan": "pro"
}
privateMetadata

Private metadata bag: server-only, never exposed to the SDK or in a JWT. Max 4096 bytes.

object
key
additional properties
any
Example
{
"stripeId": "cus_123"
}
unsafeMetadata

Unsafe metadata bag: readable and writable by the end-user via the SDK. Max 512 bytes.

object
key
additional properties
any
Example
{
"onboardingStep": 2
}

The updated user.

Media type application/json

An end-user, including server-only private metadata. Returned only on the secret-key backend API.

object
id
required

Unique identifier for this user.

string format: uuid
environmentId
required

Identifier of the environment this user belongs to.

string format: uuid
name

Full name on the profile, if any.

string | null
firstName

First (given) name on the profile, if any.

string | null
lastName

Last (family) name on the profile, if any.

string | null
locale

Preferred locale for emails and UI messages.

string | null
Allowed values: en da
status
required

Lifecycle status of the user (e.g. active, banned).

string
Allowed values: active banned deleted
createdAt
required

When this user was created (ISO-8601 UTC).

string format: date-time
updatedAt
required

When this user was last modified (ISO-8601 UTC).

string format: date-time
email

Primary email on the profile, if any.

string | null
emailVerifiedAt

When this user’s primary email was verified, if it has been verified.

string | null format: date-time
deletedAt

When this user was deleted, if soft-deleted. Null for active users.

string | null format: date-time
publicMetadata
required

Public metadata: readable by the SDK, writable only server-side.

object
key
additional properties
any
privateMetadata
required

Private metadata: server-only. Never exposed to the SDK or in a JWT.

object
key
additional properties
any
unsafeMetadata
required

Unsafe metadata: readable and writable by the end-user via the SDK.

object
key
additional properties
any
Example
{
"id": "01931a73-8b00-7000-8000-000000000000",
"environmentId": "01931a72-0000-7000-8000-000000000000",
"name": "Ada Lovelace",
"firstName": "Ada",
"lastName": "Lovelace",
"locale": "en",
"status": "active",
"createdAt": "2026-05-16T09:30:00Z",
"updatedAt": "2026-05-16T10:00:00Z",
"email": "ada@example.com",
"emailVerifiedAt": "2026-05-16T09:35:00Z",
"deletedAt": "2026-05-20T12:00:00Z",
"publicMetadata": {
"plan": "pro"
},
"privateMetadata": {
"stripeId": "cus_123"
},
"unsafeMetadata": {
"onboardingStep": 2
}
}

A bag exceeds its size limit.

Media type application/problem+json
object
type
string format: uri
title
string
status
integer format: int32
detail
string
instance
string format: uri
properties
object
key
additional properties
Example generated
{
"type": "https://example.com",
"title": "example",
"status": 1,
"detail": "example",
"instance": "https://example.com",
"properties": {
"additionalProperty": "example"
}
}

Missing or invalid secret key.

Media type application/problem+json
object
type
string format: uri
title
string
status
integer format: int32
detail
string
instance
string format: uri
properties
object
key
additional properties
Example generated
{
"type": "https://example.com",
"title": "example",
"status": 1,
"detail": "example",
"instance": "https://example.com",
"properties": {
"additionalProperty": "example"
}
}

User belongs to a different environment.

Media type application/problem+json
object
type
string format: uri
title
string
status
integer format: int32
detail
string
instance
string format: uri
properties
object
key
additional properties
Example generated
{
"type": "https://example.com",
"title": "example",
"status": 1,
"detail": "example",
"instance": "https://example.com",
"properties": {
"additionalProperty": "example"
}
}

No user with this id.

Media type application/problem+json
object
type
string format: uri
title
string
status
integer format: int32
detail
string
instance
string format: uri
properties
object
key
additional properties
Example generated
{
"type": "https://example.com",
"title": "example",
"status": 1,
"detail": "example",
"instance": "https://example.com",
"properties": {
"additionalProperty": "example"
}
}