-
Notifications
You must be signed in to change notification settings - Fork 443
publicMetadata from createInvitationBulk not transferred to user on signup #7956
Description
Description
When using createInvitationBulk with publicMetadata, the metadata is not transferred to the Clerk user object after the invitee accepts the invitation and completes signup. The docs state:
Once an invitee accepts and completes signup, these metadata will end up in the user's public metadata.
This does not happen in practice.
Steps to reproduce
- Create bulk invitations with
publicMetadata:
const client = await clerkClient()
await client.invitations.createInvitationBulk([
{
emailAddress: 'agent@example.com',
publicMetadata: { role: 'agent' },
redirectUrl: 'https://example.com/admin',
ignoreExisting: true
}
])- Invitee receives the email and completes signup
- Check the created user's
publicMetadata— it is empty ({})
Expected behavior
The user's publicMetadata should contain { role: 'agent' } after signup, as documented.
SDK investigation
Verified the SDK serialization is correct. In @clerk/backend, createInvitationBulk passes bodyParams through the standard snakecase_keys formatter:
// InvitationAPI
async createInvitationBulk(params) {
return this.request({
method: "POST",
path: joinPaths(basePath, "bulk"),
bodyParams: params // no options override
});
}
// buildRequest serializer
const formatKeys = (object) => snakecase_keys(object, { deep: false });
body: JSON.stringify(Array.isArray(bodyParams) ? bodyParams.map(formatKeys) : formatKeys(bodyParams))The top-level keys are correctly converted (publicMetadata → public_metadata), and the nested metadata object ({ role: 'agent' }) doesn't require any conversion. The request body sent to the API is valid.
This suggests the issue is server-side — the bulk endpoint accepts public_metadata but does not propagate it to the user created after the invitation is accepted.
Workaround
Explicitly set publicMetadata via updateUserMetadata in the user.created webhook handler:
await clerkClient.users.updateUserMetadata(userId, {
publicMetadata: { role: 'agent' }
})Environment
@clerk/nextjs: 6.39.0@clerk/backend: 2.33.0- Node.js: 22
- Tested with 2 separate invitees, both had empty
publicMetadataafter signup