Skip to main content
Docs

updateUserMetadata()

Updates the metadata associated with the specified user by merging existing values with the provided parameters.

A "deep" merge will be performed - "deep" means that any nested JSON objects will be merged as well. You can remove metadata keys at any level by setting their value to null.

Returns a User object.

function updateUserMetadata(userId: string, params: UpdateUserMetadataParams): Promise<User>

Note

Using clerkClient varies based on your framework. Refer to the JS Backend SDK overview for usage details, including guidance on how to access the userId and other properties.

const userId = 'user_123'

const response = await clerkClient.users.updateUserMetadata(userId, {
  publicMetadata: {
    example: 'metadata',
  },
})

Example

This example updates the user's public metadata to include a birthday, but you can update the public, private, or unsafe metadata to include any information you want.

app/api/example/route.ts
import { auth, clerkClient } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'

export async function GET() {
  const { userId } = await auth()
  const client = await clerkClient()

  await client.users.updateUserMetadata(userId, {
    publicMetadata: {
      birthday: '1990-01-01',
    },
  })

  return NextResponse.json({ success: true })
}
src/api/example.ts
import type { APIRoute } from 'astro'
import { clerkClient } from '@clerk/astro/server'

export const GET: APIRoute = async (context) => {
  const { userId } = context.locals.auth()

  await clerkClient(context).users.updateUserMetadata(userId, {
    publicMetadata: {
      birthday: '1990-01-01',
    },
  })

  return new Response(JSON.stringify({ success: true }), { status: 200 })
}
public.ts
import { getAuth, clerkClient } from '@clerk/express'

app.post('/updateBirthday', async (req, res) => {
  const { userId } = getAuth(req)

  await clerkClient.users.updateUserMetadata(userId, {
    publicMetadata: {
      birthday: '1990-01-01',
    },
  })
  res.status(200).json({ success: true })
})
app/routes/example.tsx
import { clerkClient, getAuth } from '@clerk/react-router/server'
import type { Route } from './+types/example'

export async function loader(args: Route.LoaderArgs) {
  const { userId } = await getAuth(args)

  await clerkClient.users.updateUserMetadata(userId, {
    publicMetadata: {
      birthday: '1990-01-01',
    },
  })

  return { success: true }
}
app/routes/api/example.tsx
import { json } from '@tanstack/react-start'
import { createFileRoute } from '@tanstack/react-router'
import { auth, clerkClient } from '@clerk/tanstack-react-start/server'

export const ServerRoute = createFileRoute('/api/example')({
  server: {
    handlers: {
      GET: async () => {
        const { userId } = await auth()

        await clerkClient().users.updateUserMetadata(userId, {
          publicMetadata: {
            birthday: '1990-01-01',
          },
        })

        return json({ success: true })
      },
    },
  },
})

Backend API (BAPI) endpoint

This method in the SDK is a wrapper around the BAPI endpoint PATCH/users/{user_id}/metadata. See the BAPI reference for more information.

Here's an example of making a request directly to the endpoint using cURL.

curl.sh
curl -XPATCH -H 'Authorization: Bearer CLERK_SECRET_KEY' -H "Content-type: application/json" -d '{
  "public_metadata": {
    "birthday": "1990-01-01"
  }
}' 'https://api.clerk.com/v1/users/{user_id}/metadata'

Feedback

What did you think of this content?

Last updated on