> ## Documentation Index
> Fetch the complete documentation index at: https://docs.asteragents.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update User Metadata

> Update organization-scoped metadata for a specific user

<Note>
  This endpoint requires organization admin privileges. Only users with the `org:admin` role can update user metadata.
</Note>

<Info>
  **Organization-Scoped Metadata**: Metadata set through this endpoint is specific to the user's membership in your organization. If the same user belongs to multiple organizations, each organization maintains separate metadata.
</Info>

Update custom metadata for a user within your organization. Perfect for managing user roles, departments, teams, or any custom properties needed for filtering and organization.

### Authentication

<ParamField header="Authorization" type="string" required>
  Bearer token for authentication. Must be from a user with `org:admin` role.
</ParamField>

### Body

<ParamField body="userId" type="string" required>
  Clerk user ID of the user whose metadata should be updated
</ParamField>

<ParamField body="metadata" type="object" required>
  Key-value pairs of metadata to set for the user. This completely replaces existing metadata.

  <Expandable title="Common Metadata Fields">
    * `role`: User's role or job title (e.g., "manager", "developer")
    * `department`: Department name (e.g., "engineering", "marketing")
    * `team`: Team assignment (e.g., "backend", "frontend")
    * `level`: Seniority level (e.g., "senior", "junior")
    * `vnum`: Vendor or employee number
    * Custom fields: Any key-value pairs relevant to your organization
  </Expandable>
</ParamField>

### Response

<ResponseField name="success" type="boolean">
  Whether the metadata update was successful
</ResponseField>

<ResponseField name="user" type="object">
  Updated user information

  <Expandable title="User Object">
    <ResponseField name="id" type="string">
      Clerk user ID
    </ResponseField>

    <ResponseField name="email" type="string">
      User's email address
    </ResponseField>

    <ResponseField name="firstName" type="string" nullable>
      User's first name
    </ResponseField>

    <ResponseField name="lastName" type="string" nullable>
      User's last name
    </ResponseField>

    <ResponseField name="publicMetadata" type="object">
      The updated organization-scoped metadata
    </ResponseField>
  </Expandable>
</ResponseField>

### Examples

<CodeGroup>
  ```curl Basic Update theme={null}
  curl -X POST https://asteragents.com/api/admin/updateUserMetadata \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "userId": "user_2ABC123DEF",
      "metadata": {
        "role": "senior-developer",
        "department": "engineering",
        "team": "backend"
      }
    }'
  ```

  ```python theme={null}
  import requests

  url = "https://asteragents.com/api/admin/updateUserMetadata"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN",
      "Content-Type": "application/json"
  }
  data = {
      "userId": "user_2ABC123DEF",
      "metadata": {
          "role": "manager",
          "department": "engineering",
          "level": "senior",
          "vnum": "EMP-12345"
      }
  }

  response = requests.post(url, headers=headers, json=data)
  result = response.json()
  print(f"Updated metadata for {result['user']['email']}")
  ```

  ```javascript theme={null}
  const response = await fetch('https://asteragents.com/api/admin/updateUserMetadata', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_TOKEN',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      userId: 'user_2ABC123DEF',
      metadata: {
        role: 'developer',
        department: 'engineering',
        team: 'frontend'
      }
    })
  });

  const result = await response.json();
  console.log('Updated user:', result.user.email);
  ```

  ```json Success Response theme={null}
  {
    "success": true,
    "user": {
      "id": "user_2ABC123DEF",
      "email": "john.doe@company.com",
      "firstName": "John",
      "lastName": "Doe",
      "publicMetadata": {
        "role": "senior-developer",
        "department": "engineering",
        "team": "backend"
      }
    }
  }
  ```
</CodeGroup>

### Error Codes

<ResponseField name="400" type="object">
  Bad Request - Invalid request data or validation errors
</ResponseField>

<ResponseField name="401" type="object">
  Unauthorized - Invalid or missing authentication
</ResponseField>

<ResponseField name="403" type="object">
  Forbidden - User is not an admin in the organization, or target user is not a member of the organization
</ResponseField>

<ResponseField name="405" type="object">
  Method Not Allowed - Only POST requests are accepted
</ResponseField>

<ResponseField name="500" type="object">
  Internal Server Error - Unexpected error occurred
</ResponseField>

## Use Cases

### Department Management

Assign users to departments for organizational filtering:

```javascript theme={null}
await fetch('/api/admin/updateUserMetadata', {
  method: 'POST',
  headers: headers,
  body: JSON.stringify({
    userId: 'user_123',
    metadata: {
      department: 'marketing',
      role: 'content-writer',
      team: 'social-media'
    }
  })
});
```

### Role-Based Access Control

Set roles that can be used for filtering in the dashboard:

```python theme={null}
# Promote user to manager
requests.post('/api/admin/updateUserMetadata',
    headers=headers,
    json={
        'userId': 'user_456',
        'metadata': {
            'role': 'manager',
            'department': 'engineering',
            'level': 'senior',
            'manages_team': 'backend'
        }
    })
```

### Custom Properties

Store any custom data relevant to your organization:

```javascript theme={null}
// Track contractor information
await fetch('/api/admin/updateUserMetadata', {
  method: 'POST',
  headers: headers,
  body: JSON.stringify({
    userId: 'user_789',
    metadata: {
      employment_type: 'contractor',
      contract_end_date: '2024-12-31',
      hourly_rate: 'tier-3',
      vnum: 'CON-9876'
    }
  })
});
```

## Workflow

### Step 1: Get User ID

First, retrieve the user ID from the [Get Organization Users](/api-reference/endpoint/get-users-in-org) endpoint:

```javascript theme={null}
const usersResponse = await fetch('/api/admin/getUsersInOrg', {
  headers: { 'Authorization': 'Bearer ' + token }
});
const users = await usersResponse.json();

// Find the user you want to update
const targetUser = users.find(u => u.email === 'john@company.com');
```

### Step 2: Update Metadata

Then update their metadata:

```javascript theme={null}
await fetch('/api/admin/updateUserMetadata', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ' + token,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    userId: targetUser.id,
    metadata: {
      role: 'senior-developer',
      department: 'engineering'
    }
  })
});
```

## Features

**Organization Isolation**: Complete metadata separation between organizations.

* **Per-Organization Metadata**: Same user in different orgs has independent metadata
* **Complete Replacement**: Metadata object completely replaces existing metadata (not merged)
* **Real-time Updates**: Changes are immediately reflected in dashboard filters and user listings
* **Flexible Schema**: Store any JSON-serializable data structure
* **Dashboard Integration**: Use metadata for filtering conversations and statistics

## Important Notes

<Warning>
  **Metadata Replacement**: This endpoint completely replaces the user's metadata in your organization. To preserve existing fields, fetch current metadata first and merge your changes before updating.
</Warning>

* Metadata is scoped to the organization - each org maintains separate metadata for shared users
* Removing a user from the organization deletes their metadata for that org
* Re-adding a user creates fresh metadata (previous metadata is not restored)
* Metadata can contain any JSON-serializable data (strings, numbers, booleans, objects, arrays)
* Changes are reflected immediately in [dashboard filters](/api-reference/endpoint/dashboard-interactions)

## Security Notes

* Only organization admins can update user metadata
* Target user must be a member of your organization
* Cannot update metadata for users in other organizations
* Metadata is visible in API responses to all org members

<Tip>
  Use this endpoint with [Get Organization Users](/api-reference/endpoint/get-users-in-org) to build powerful user management workflows and custom dashboards.
</Tip>
