-
Notifications
You must be signed in to change notification settings - Fork 1k
New API version release #3380
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
brunol95
wants to merge
7
commits into
main
Choose a base branch
from
bruno/user-5311-latest-api-version
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
New API version release #3380
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
70920c3
draft for new api versionn changes
brunol95 1563598
update rate limit for user data
brunol95 6e8e606
Merge branch 'main' into bruno/user-5311-latest-api-version
alexisintech 5b8d164
update mobile refs with updateMetadata method
brunol95 87220cc
Merge branch 'bruno/user-5311-latest-api-version' of https://github.c…
brunol95 3081b84
Merge branch 'main' into bruno/user-5311-latest-api-version
brunol95 3414da8
docs: Fix metadata example diff highlighting, NOTE callouts, and para…
manovotny File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
docs/guides/development/upgrading/upgrade-guides/2026-05-12.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| --- | ||
| title: Upgrade to API version 2026-05-12 | ||
| description: Learn how to upgrade to version 2026-05-12 of Clerk's API. | ||
| --- | ||
|
|
||
| **Version 2026-05-12** of Clerk's Frontend and Backend APIs removes user metadata fields from the general-purpose user update endpoints. Metadata must now be set through the dedicated metadata endpoints, which provide deep-merge semantics. | ||
|
|
||
| To use this new API version, refer to the [versioning guide](/docs/guides/development/upgrading/versioning). This guide documents all updates at the API level. Since implementation details may differ between SDKs, it will help you identify which parts of your SDK usage may require additional review in the documentation, and assist consumers using unofficial or custom API clients in managing the upgrade. | ||
|
|
||
| ## Backend endpoint changes | ||
|
|
||
| `PATCH /v1/users/{user_id}` no longer accepts the following fields in the request body: | ||
|
|
||
| - `public_metadata` | ||
| - `private_metadata` | ||
| - `unsafe_metadata` | ||
|
|
||
| To update user metadata, use one of the dedicated endpoints below: | ||
|
|
||
| | Endpoint | Semantics | | ||
| | - | - | | ||
| | `PATCH /v1/users/{user_id}/metadata` | Deep-merges the provided values into the existing metadata. Any key set to `null` is removed. | | ||
| | `PUT /v1/users/{user_id}/metadata` | Replaces each provided top-level metadata field in full — no merging at any level. Top-level fields omitted from the request body are left untouched. Send `{}` to clear a field, or `null` to store a JSON `null` value. | | ||
|
|
||
| Choose `PATCH` when you want to update specific keys without affecting others, and `PUT` when you want to overwrite an entire metadata field. | ||
|
|
||
| If you are using a Clerk SDK, use the [`updateUserMetadata()`](/docs/reference/backend/user/update-user-metadata) method (which wraps `PATCH`) or the [`replaceUserMetadata()`](/docs/reference/backend/user/replace-user-metadata) method (which wraps `PUT`) instead of passing metadata fields to `updateUser()`. | ||
|
|
||
| ```ts {{ del: [[1, 5]], ins: [[6, 10], [12, 16]] }} | ||
| await clerkClient.users.updateUser(userId, { | ||
| publicMetadata: { | ||
| role: 'admin', | ||
| }, | ||
| }) | ||
| await clerkClient.users.updateUserMetadata(userId, { | ||
| publicMetadata: { | ||
| role: 'admin', | ||
| }, | ||
| }) | ||
|
|
||
| await clerkClient.users.replaceUserMetadata(userId, { | ||
| publicMetadata: { | ||
| role: 'admin', | ||
| }, | ||
| }) | ||
| ``` | ||
|
|
||
| ## Frontend endpoint changes | ||
|
|
||
| `PATCH /v1/me` no longer accepts the `unsafe_metadata` field in the request body. | ||
|
|
||
| To update unsafe metadata from the frontend, use the dedicated endpoint `PATCH /v1/me/metadata` instead. This endpoint deep-merges the provided value with the existing `unsafeMetadata`, and any key set to `null` is removed. | ||
|
|
||
| If you are using a Clerk SDK, use the [`updateMetadata()`](/docs/reference/objects/user#update-metadata) method on the `User` object instead of passing `unsafeMetadata` to `update()`. | ||
|
|
||
| ```ts {{ del: [[1, 6]], ins: [[7, 9]] }} | ||
| await user.update({ | ||
| unsafeMetadata: { | ||
| ...user.unsafeMetadata, | ||
| theme: 'dark', | ||
| }, | ||
| }) | ||
| await user.updateMetadata({ | ||
| unsafeMetadata: { theme: 'dark' }, | ||
| }) | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| --- | ||
| title: '`replaceUserMetadata()`' | ||
| description: Use the replaceUserMetadata() method to fully replace the metadata associated with the specified user. | ||
| --- | ||
|
|
||
| Replaces the metadata associated with the specified user. Unlike [`updateUserMetadata()`](/docs/reference/backend/user/update-user-metadata), which deep-merges into the existing metadata, this method uses replace semantics: when a metadata field is provided, its previous value is overwritten in full with no merging at any level. | ||
|
|
||
| The distinction is at two layers: | ||
|
|
||
| - **Top-level field omission preserves the existing value.** Each top-level field (`publicMetadata`, `privateMetadata`, `unsafeMetadata`) is handled independently. If you don't include a field in the request, the stored value for that field is left untouched. | ||
| - **The value inside a provided field is replaced in full.** When you do include a field, its previous content is discarded — any nested keys present before but absent in the new value are dropped. There is no merge. | ||
|
|
||
| For the provided field, you can also send: | ||
|
|
||
| - `{}` (empty object) to clear the field. | ||
| - `null` to overwrite the field with a JSON `null` value. Prefer `{}` unless you specifically need a stored `null`. | ||
|
|
||
| Returns a [`User`](/docs/reference/backend/types/backend-user) object. | ||
|
|
||
| ```ts | ||
| function replaceUserMetadata(userId: string, params: UserMetadataParams): Promise<User> | ||
| ``` | ||
|
|
||
| ## `UserMetadataParams` | ||
|
|
||
| <Properties> | ||
| - `userId` | ||
| - `string` | ||
|
|
||
| The ID of the user to update. | ||
|
|
||
| --- | ||
|
|
||
| - `publicMetadata?` | ||
| - [`UserPublicMetadata`](/docs/reference/types/metadata#user-public-metadata) | ||
|
|
||
| Metadata that can be read from the Frontend API and [Backend API](/docs/reference/backend-api){{ target: '_blank' }} and can be set only from the Backend API. When provided, the entire stored `publicMetadata` is overwritten with this value. When omitted, the existing `publicMetadata` is preserved. | ||
|
|
||
| --- | ||
|
|
||
| - `privateMetadata?` | ||
| - [`UserPrivateMetadata`](/docs/reference/types/metadata#user-private-metadata) | ||
|
|
||
| Metadata that can be read and set only from the [Backend API](/docs/reference/backend-api){{ target: '_blank' }}. When provided, the entire stored `privateMetadata` is overwritten with this value. When omitted, the existing `privateMetadata` is preserved. | ||
|
|
||
| --- | ||
|
|
||
| - `unsafeMetadata?` | ||
| - [`UserUnsafeMetadata`](/docs/reference/types/metadata#user-unsafe-metadata) | ||
|
|
||
| Metadata that can be read and set from the Frontend API. It's considered unsafe because it can be modified from the frontend. When provided, the entire stored `unsafeMetadata` is overwritten with this value. When omitted, the existing `unsafeMetadata` is preserved. | ||
| </Properties> | ||
|
|
||
| ## Usage | ||
|
|
||
| <Include src="_partials/backend/usage" /> | ||
|
|
||
| ```tsx | ||
| const userId = 'user_123' | ||
|
|
||
| const response = await clerkClient.users.replaceUserMetadata(userId, { | ||
| publicMetadata: { | ||
| role: 'admin', | ||
| }, | ||
| }) | ||
| ``` | ||
|
|
||
| ## Backend API (BAPI) endpoint | ||
|
|
||
| This method in the SDK is a wrapper around the BAPI endpoint `PUT/users/{user_id}/metadata`. See the [BAPI reference](/docs/reference/backend-api/tag/users/put/users/\{user_id}/metadata){{ target: '_blank' }} for more information. | ||
|
|
||
| Here's an example of making a request directly to the endpoint using cURL. | ||
|
|
||
| <SignedOut> | ||
| Replace `YOUR_SECRET_KEY` with your Clerk Secret Key. You can find your Secret Key on the [**API keys**](https://dashboard.clerk.com/~/api-keys) page in the Clerk Dashboard. | ||
| </SignedOut> | ||
|
|
||
| ```bash {{ filename: 'curl.sh' }} | ||
| curl -XPUT -H 'Authorization: Bearer {{secret}}' -H "Content-type: application/json" -d '{ | ||
| "public_metadata": { | ||
| "role": "admin" | ||
| } | ||
| }' 'https://api.clerk.com/v1/users/{user_id}/metadata' | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving a comment to flag that TBDs need to be fixed before merge. From @brunol95: