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

# User profile fields

> Pin a field so ingestion stops overwriting it, and hand it back when you're done

Six user profile fields are **governed**: Serval tracks where each value came from and decides who is allowed to change it next. If a workflow sets a user's locale and the nightly directory sync keeps reverting it, this page explains why and how to make the value stick.

The governed fields are `first_name`, `last_name`, `avatar_url`, `timezone`, `locale`, and `manager`. Every other user field—email, role, phone number—is ungoverned: the last write wins.

## Who wins

Three classes of writer compete for a governed field. The highest-ranked writer that has touched the field owns it.

| Rank | Writer                     | How a value gets here                                                                           |
| :--- | :------------------------- | :---------------------------------------------------------------------------------------------- |
| 1    | **Directory sync**         | Your IdP, through SCIM or directory sync. Locks the field against everyone else, including you. |
| 2    | **Pinned deliberate edit** | A person editing in the Serval UI, or an API call that pinned the field. Blocks automation.     |
| 3    | **Automation**             | User ingestion, connected apps, and unpinned API calls.                                         |

A pin protects a field from automation. It doesn't protect it from directory sync: if your IdP supplies a value, change it in the IdP.

## Pinning depends on your token

Whether a write pins by default depends on how you authenticated:

* **User token**: pins by default. A person editing their own profile owns that value.
* **API key or worker token**: doesn't pin. Your write stays automation-class unless you ask for a pin explicitly.

That default is why a workflow's edits get overwritten: an API key writing `locale` looks identical to ingestion writing `locale`, so the next sync is free to replace it.

## Pin a field

List the field in `pinFields` on `PUT /v2/users/{id}`:

```json theme={null}
{
  "locale": "fr-FR",
  "pinFields": ["USER_PROFILE_FIELD_LOCALE"]
}
```

The field is now pinned. Ingestion and connected apps can no longer change it, and it stays pinned until you release it or a later deliberate edit replaces it.

<Note>A pinned field must be **set in the same request**. You can't pin a value that's already stored. Send the value and the pin together, so the request's outcome doesn't depend on state you can't see.</Note>

Two fields are special:

* **`avatar_url` can't be pinned.** Avatars live under a predictable key that automation can overwrite in place, so a pin wouldn't protect the image. Listing it returns `400`.
* **`manager` pins through the relationship endpoints**, not here. See [Manager](#manager).

An explicit pin replaces whatever pin was there before, including one a person set in the UI. Reach for it only when your workflow should own the field.

You can also pin at creation time. `POST /v2/users` accepts `pinFields` for the two fields you can seed there, `first_name` and `last_name`:

```json theme={null}
{
  "email": "ada@example.com",
  "firstName": "Ada",
  "pinFields": ["USER_PROFILE_FIELD_FIRST_NAME"]
}
```

Without pins, the values you seed at creation stay open for ingestion to enrich.

## When your write doesn't land

An API-key write to a field someone else owns doesn't fail. Serval applies the rest of the update and tells you what it skipped:

```json theme={null}
{
  "data": { "...": "the updated user" },
  "skippedPinnedFields": ["USER_PROFILE_FIELD_FIRST_NAME"],
  "skippedDirectoryLockedFields": ["USER_PROFILE_FIELD_LAST_NAME"]
}
```

The response is still `200`. Check these two arrays if your workflow depends on the write landing.

* `skippedPinnedFields`: a person, or another deliberate edit, owns this field. Send `pinFields` to take ownership.
* `skippedDirectoryLockedFields`: your IdP supplies this field. Change it there. No API call can take it.

Two details worth knowing:

* If you write the value a pin already holds, the request succeeds cleanly and the field isn't reported as skipped. Re-asserting the current state is a no-op, not a conflict.
* A directory-locked field is **always** reported, even when your value matches. Serval checks the lock before comparing values.

<Warning>User tokens behave differently. A user-token write replaces pins without complaint, but a write to a directory-locked field fails the entire request with `400` rather than skipping the field.</Warning>

## Release a field

Releasing hands a field back to automation. The current value stays, but loses its protection, so the next sync may replace it.

```json theme={null}
{
  "releaseFields": ["USER_PROFILE_FIELD_LOCALE"]
}
```

Release works with both user tokens and API keys: if you can pin a field, you can hand it back. You can't set and release the same field in one request.

## Manager

`manager` is written through the relationship endpoints rather than `PUT /v2/users/{id}`, so its pin lives there too.

Assign a manager with `POST /v2/user-relationships` and pin the assignment:

```json theme={null}
{
  "userId": "<user-id>",
  "relatedUserId": "<manager-id>",
  "relationshipType": "USER_RELATIONSHIP_TYPE_MANAGER",
  "pin": true
}
```

Clear a manager with `DELETE /v2/user-relationships/{user_id}`, passing `pin` as a query parameter. Pinning a delete pins the *cleared* state, so ingestion can't re-assign the manager it thinks the user should have.

The same token defaults apply: user tokens pin, API keys don't. Pass `pin: false` from a user token to assign a manager **without** taking ownership of the field.

To hand the manager field back to ingestion, release it through `PUT /v2/users/{id}`:

```json theme={null}
{
  "releaseFields": ["USER_PROFILE_FIELD_MANAGER"]
}
```

## What's next

<CardGroup cols={2}>
  <Card title="Update User" icon="user-pen" href="/api-reference/user-api/update-user">
    Full request and response schema, including `pinFields` and `releaseFields`.
  </Card>

  <Card title="Create User Relationship" icon="sitemap" href="/api-reference/user-relationship-api/create-user-relationship">
    Assign a manager and pin the reporting line.
  </Card>

  <Card title="Connect your IdP" icon="id-card" href="/sections/access-management/configuration/connect-idp">
    Directory sync outranks every pin. Fields your IdP supplies are changed there.
  </Card>

  <Card title="Databases field precedence" icon="database" href="/sections/documentation/databases/manual-data-entry">
    The equivalent model for Databases item types.
  </Card>
</CardGroup>
