For AI agents: markdown of this page — /docs-content-en/entities/users/photo-delete.md documentation index — /llms.txt
Remove employee photo
DELETE /v1/users/:id/personal-photo
Removes an employee's profile photo. This is the only command that removes it: writing the personalPhoto field on an update does not remove the photo on any surface. The operation is irreversible — Bitrix24 deletes the file itself, so re-uploading the same image produces a new identifier and a new URL. Requires Bitrix24 account administrator rights, or ownership of that profile — Bitrix24 makes that decision.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
id (path) |
number | yes | Employee ID. List: GET /v1/users |
The request has no body.
Examples
curl — personal key
curl -X DELETE "https://vibecode.bitrix24.com/v1/users/1331/personal-photo" \
-H "X-Api-Key: YOUR_API_KEY"
curl — OAuth application
curl -X DELETE "https://vibecode.bitrix24.com/v1/users/1331/personal-photo" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
JavaScript — personal key
const res = await fetch('https://vibecode.bitrix24.com/v1/users/1331/personal-photo', {
method: 'DELETE',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
},
})
const { success, data } = await res.json()
if (success && data.removed) {
console.log(`Photo of employee ${data.id} removed`)
}
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/users/1331/personal-photo', {
method: 'DELETE',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { success, data } = await res.json()
Response fields
| Field | Type | Description |
|---|---|---|
success |
boolean | Always true on a successful removal |
data.id |
number | ID of the employee whose photo was removed |
data.personalPhoto |
null | Always null — the state of the field after the call |
data.removed |
boolean | Always true — an explicit marker of the operation's semantics |
data.user |
object | Full employee record after the removal. The field is absent when the re-read of the record fails — the photo is removed either way |
Response example
{
"success": true,
"data": {
"id": 1331,
"personalPhoto": null,
"removed": true,
"user": {
"id": 1331,
"name": "John",
"lastName": "Brown",
"email": "john.brown@example.com",
"active": true,
"workPosition": "Manager",
"departmentId": [1]
}
}
}
Error response example
403 — Bitrix24 refused the write; the photo stayed in place:
{
"success": false,
"error": {
"code": "UPDATE_FAILED",
"message": "Bitrix24 rejected user.update for the photo removal (result: false)",
"hint": "Bitrix24 returns false when the calling user lacks portal admin rights (a user may still edit their OWN profile), or when the target user id does not exist. The photo is unchanged."
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_ID |
:id is not a positive integer |
| 401 | MISSING_API_KEY |
The X-Api-Key header was not sent |
| 401 | TOKEN_MISSING |
The API key has no configured tokens |
| 403 | SCOPE_DENIED |
The API key lacks the user scope |
| 403 | WRITE_BLOCKED_READONLY_KEY |
The key was issued in read-only mode |
| 403 | UPDATE_FAILED |
Bitrix24 returned result: false. This is the response to a call on someone else's profile without Bitrix24 account administrator rights, and to a call on an :id that does not exist. The photo is unchanged |
| 429 | RATE_LIMITED |
The request rate on the Bitrix24 side was exceeded |
| 429 | OPERATION_TIME_LIMIT |
Bitrix24 paused this method for your key: the method exhausted its operating-time budget. The retry delay arrives in error.retryAfter and in the Retry-After header |
| 429 | QUEUE_OVERFLOW, QUEUE_TIMEOUT |
The portal request queue is full or the request did not get through the queue in time. The Retry-After header suggests the delay |
Full list of common API errors — Errors.
Known specifics
Idempotency. For an employee with no photo the call also answers 200 with removed: true. There
is no need to check whether a photo exists before clearing it.
Writing the field does not remove the photo. Before this command an empty string in personalPhoto reached
Bitrix24 as an instruction to remove the photo, and the update answered with success after the deletion had
happened. The field now behaves like this on update:
| Update surface | a value that cannot be turned into a file | personalPhoto: null |
|---|---|---|
PATCH /v1/users/:id |
400 INVALID_PARAMS before the Bitrix24 call |
accepted, never reaches the removal branch, the photo stays |
POST /v1/users/batch (action: update) |
refused with 400 BATCH_ITEM_VALIDATION, the whole batch is not sent |
accepted, the key never reaches Bitrix24, the photo stays |
POST /v1/batch (action: update) |
refused with INVALID_PARAMS in data.errors of that sub-call |
refused with INVALID_PARAMS in data.errors of that sub-call |
The difference on null is not an accident: the reason lies in how each surface encodes the request. The single PATCH sends a JSON body,
where null stays null and Bitrix24 skips it. A per-entity batch sub-call travels as a query string,
and the encoder drops a null key entirely. The global batch encoder writes PERSONAL_PHOTO= instead,
that is, an empty string — the same remove-the-photo command, which is why null is refused there. The
field's value does not remove the photo on any of the three surfaces — only this command does.
Batch calls do not support it. A batch sub-call is addressed by an entity plus an action
(list, get, create, update, delete, fields, search), and a nested resource cannot be
expressed in that form. Remove a photo with a single call.
Replacement instead of removal. To set a different photo, you do not need to remove the current one: send the
[file name, base64] pair in personalPhoto to POST /v1/users or
PATCH /v1/users/:id.