# Set your photo

> The users.avatar.set operation: PUT /api/v1/users/me/avatar in the REST API and the users_avatar_set tool in the MCP server.

Uploads your photo, shown instead of your initials: in the account menu and to the people in your
organizations. Send it base64-encoded in `content`: a square PNG, JPEG or WebP image of at most 512 KB and
1024 × 1024 pixels. The type is read from the bytes; SVG and GIF are refused. The console crops and resizes the
photo to 256 × 256 in the browser before it uploads it, which also removes metadata such as where it was taken.

The photo is private: it is served at its `avatar.url` (`/media/{fileId}/{sha256}.{ext}`) only to you, to the
members of your organizations and to Ownrecord staff. The photo it replaces is deleted from storage. Uploading
the same photo again changes nothing. Ownrecord never shows the picture of your Google or Microsoft account.
Dry-run it to check a photo without storing it.

**Who can call it:** the signed-in user, for their own account, in the console.

## At a glance

- **REST:** `PUT /api/v1/users/me/avatar`
- **MCP tool:** `users_avatar_set`
- **Operation ID:** `users.avatar.set`
- **Scope:** Platform
- **Permission:** `account:write`
- **Risk tier:** `write`
- **Dry run:** Supported (send `Ownrecord-Dry-Run: true`)
- **Idempotency:** `Idempotency-Key` optional
- **Modes:** Test and live
- **Authentication:** API key with the `account:write` scope
- **Since:** M13

## Request

### Body

A JSON object (`Content-Type: application/json`):

| Field     | Type   | Required | Description                                                                                                                                           |
| --------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `content` | string | Yes      | The photo's bytes, base64-encoded: a square PNG, JPEG or WebP image of at most 512 KB and 1024 × 1024 pixels (256 × 256 is what the console uploads). |

## Response

`200 OK` with a JSON object:

| Field           | Type             | Description                                                                                                     |
| --------------- | ---------------- | --------------------------------------------------------------------------------------------------------------- |
| `object`        | `"user_profile"` |                                                                                                                 |
| `id`            | `usr_…` ID       |                                                                                                                 |
| `email`         | string           | Your account's address (changed with `users.email_change.start`).                                               |
| `name`          | string or null   | Your display name, or null when there is none yet.                                                              |
| `nameSetByUser` | boolean          | Whether you set the name yourself. Until you do, a Google or Microsoft sign-in may update it from that account. |
| `avatar`        | object or null   | Your uploaded photo (private: shown to you, to the people in your organizations and to staff), or null.         |
| `updatedAt`     | date-time        |                                                                                                                 |

## Examples

### Upload my photo

```http
PUT /api/v1/users/me/avatar
Authorization: Bearer or_test_…
Content-Type: application/json

{
  "content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
}
```

Response (`200`):

```json
{
  "object": "user_profile",
  "id": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
  "email": "ana@acme.example",
  "name": "Ana Novak",
  "nameSetByUser": true,
  "avatar": {
    "fileId": "file_01m4tx5nj8emwbyf7y9vcf47yc",
    "url": "/media/file_01m4tx5nj8emwbyf7y9vcf47yc/63ef318d96b5d0d0ceba6e04a4e622b1158335cdc67c49e27839132c6f655058.png"
  },
  "updatedAt": "2026-11-05T09:00:00.000Z"
}
```

## Errors

| Code                                                                                                   | HTTP status | When                                                                                                            | What to do                                                                                                                                                          |
| ------------------------------------------------------------------------------------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed)                 | 400         | `content` isn't base64, or is far larger than an image may be (`param` names the field).                        | Fix the fields listed in `details.issues` and send the request again.                                                                                               |
| [`image_type_unsupported`](https://ownrecord.io/docs/reference/errors.md#image_type_unsupported)       | 400         | The file isn't a still PNG, JPEG or WebP image (read from its bytes): SVG, GIF and animations are refused.      | Export the image as PNG, JPEG or WebP (a still image, not an animation) and upload it again. The type is read from the file's bytes, not from its name.             |
| [`image_too_large`](https://ownrecord.io/docs/reference/errors.md#image_too_large)                     | 400         | The image is larger than 512 KB.                                                                                | Resize or compress the image to at most 512 KB. Avatars and icons are shown at 256 × 256 pixels and logos within 600 × 200, so a small file loses nothing.          |
| [`image_dimensions`](https://ownrecord.io/docs/reference/errors.md#image_dimensions)                   | 400         | The image is wider or taller than 1024 pixels, or not square (avatars and icons), or a logo outside 1:1 to 4:1. | Use a square image of at most 1024 × 1024 pixels for avatars and icons, and a logo between square and four times as wide as it is tall, at most 1024 pixels a side. |
| [`upstream_timeout`](https://ownrecord.io/docs/reference/errors.md#upstream_timeout)                   | 502         | The file store didn't answer in time; nothing was recorded. Retry.                                              | Retry the request with the same Idempotency-Key after a short wait.                                                                                                 |
| [`profile_photo_unavailable`](https://ownrecord.io/docs/reference/errors.md#profile_photo_unavailable) | 500         | The platform isn't set up yet.                                                                                  | Try again later. If it persists, contact support with the request ID.                                                                                               |
| [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict)                   | 409         | Your account changed at the same time; retry.                                                                   | Fetch the object again and retry the change.                                                                                                                        |
| [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied)                 | 403         | The caller isn't a person signed in to the console.                                                             | Ask an organization owner or admin for a role or scope that allows this action.                                                                                     |

It can also return these [common errors](https://ownrecord.io/docs/reference.md#common-errors): [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`invalid_json`](https://ownrecord.io/docs/reference/errors.md#invalid_json), [`unsupported_media_type`](https://ownrecord.io/docs/reference/errors.md#unsupported_media_type), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found), [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused), [`idempotency_in_progress`](https://ownrecord.io/docs/reference/errors.md#idempotency_in_progress), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
