
# Update your profile

`PATCH /fapi/v1/me` · called from the environment's sign-in host

Changes the authenticated user's profile fields. A field present in the body is changed, an absent field is left as it is, and an empty string or `null` clears the field. `user_metadata`, when given, is merged as an RFC 7396 merge patch. The same field rules as the management API apply. Requires the authenticated user's `__Host-idp_session` cookie; no recent re-verification is needed. A first-party app on another origin can instead send its front API access token (`Authorization: DPoP <token>` with a DPoP proof; see [Front API access token](/docs/api/fapi/front-api-token)).

Field errors (`422 validation_failed`, in `errors[]`): `invalid` (format or length; `/locale` also when the language is not enabled for the environment), `too_large` and `too_many_keys` (`user_metadata` over 16 KiB, depth 5 or 100 top-level keys), `identifier_type_disabled` (usernames are turned off in the environment), `profile_field_disabled` (the environment turned the field off; clearing it is still allowed) and `profile_field_required` (the environment requires the field, so it cannot be cleared).

## Request

Headers:

| Header | Required | Description |
| --- | --- | --- |
| `Idp-Client` | yes | SDK identifier. |
| `Origin` | yes | Must be exactly `https://<sign-in host>`. |
| `If-Match` | no | Optional. The `ETag` of a previous answer (or `*`); the change is made only if the profile is still at that version. |

Body (`application/json` or `application/merge-patch+json`):

| Field | Type | Description |
| --- | --- | --- |
| `given_name` | string or null | Given name. |
| `family_name` | string or null | Family name. |
| `name` | string or null | Full name. |
| `picture` | string or null | Picture URL (`https`). |
| `locale` | string or null | Language (BCP 47 tag). |
| `zoneinfo` | string or null | Time zone (IANA name). |
| `username` | string or null | Username. |
| `user_metadata` | object | Merge patch applied to `user_metadata` (RFC 7396). |

```json
{
  "given_name": "Ada",
  "zoneinfo": "",
  "user_metadata": {
    "theme": null
  }
}
```

## Response

`200 OK` with the updated profile (same fields as `GET /fapi/v1/me`) and a new `ETag`.

## Errors

| Status | Code | When |
| --- | --- | --- |
| 400 | `malformed_request` | The body or the `If-Match` header is malformed. |
| 400 | `unknown_field` | The body has a field that cannot be changed here (for example `email` or `app_metadata`). |
| 401 | `unauthenticated` | No valid session cookie. |
| 403 | `origin_not_allowed` | `Origin` is missing or wrong. |
| 404 | `not_found` | The account cannot be read (for example blocked or being deleted). |
| 409 | `username_unavailable` | The username is reserved or already used by another account (both answer the same). |
| 412 | `precondition_failed` | `If-Match` does not match the current version; nothing changed. |
| 413 | `payload_too_large` | The body exceeds 16 KiB. |
| 415 | `unsupported_media_type` | Unsupported `Content-Type`. |
| 422 | `validation_failed` | A field breaks a rule; `errors[]` names the field and the reason (see above). |
| 503 | `service_unavailable` | The user directory is temporarily unavailable; retry after `Retry-After` seconds. |

## Example

```bash
curl -X PATCH https://example.keenauth.app/fapi/v1/me \
  -H "Idp-Client: my-app/1.0.0 (node/22.0.0)" \
  -H "Origin: https://example.keenauth.app" \
  -H 'If-Match: "7"' \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{"given_name":"Ada","zoneinfo":""}'
```

## Personal data

This endpoint carries personal data: end-user profile. [Personal data in the KeenAuth APIs](/docs/policies/personal-data) describes what is stored, how long it is kept and how it is deleted. Do not send special categories of personal data (health, biometric data, religion, political opinions, sexual orientation) in any field.
