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 | Required | Description |
|---|---|---|---|
Parameterid (path) |
Typenumber | Requiredyes | DescriptionEmployee 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 |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true on a successful removal |
Fielddata.id |
Typenumber | DescriptionID of the employee whose photo was removed |
Fielddata.personalPhoto |
Typenull | DescriptionAlways null — the state of the field after the call |
Fielddata.removed |
Typeboolean | DescriptionAlways true — an explicit marker of the operation's semantics |
Fielddata.user |
Typeobject | DescriptionFull 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 |
|---|---|---|
| HTTP400 | CodeINVALID_ID |
Description:id is not a positive integer |
| HTTP401 | CodeMISSING_API_KEY |
DescriptionThe X-Api-Key header was not sent |
| HTTP401 | CodeTOKEN_MISSING |
DescriptionThe API key has no configured tokens |
| HTTP403 | CodeSCOPE_DENIED |
DescriptionThe API key lacks the user scope |
| HTTP403 | CodeWRITE_BLOCKED_READONLY_KEY |
DescriptionThe key was issued in read-only mode |
| HTTP403 | CodeUPDATE_FAILED |
DescriptionBitrix24 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 |
| HTTP429 | CodeRATE_LIMITED |
DescriptionThe request rate on the Bitrix24 side was exceeded |
| HTTP429 | CodeOPERATION_TIME_LIMIT |
DescriptionBitrix24 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 |
| HTTP429 | CodeQUEUE_OVERFLOW, QUEUE_TIMEOUT |
DescriptionThe 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 |
|---|---|---|
Update surfacePATCH /v1/users/:id |
a value that cannot be turned into a file400 INVALID_PARAMS before the Bitrix24 call |
personalPhoto: nullaccepted, never reaches the removal branch, the photo stays |
Update surfacePOST /v1/users/batch (action: update) |
a value that cannot be turned into a filerefused with 400 BATCH_ITEM_VALIDATION, the whole batch is not sent |
personalPhoto: nullaccepted, the key never reaches Bitrix24, the photo stays |
Update surfacePOST /v1/batch (action: update) |
a value that cannot be turned into a filerefused with INVALID_PARAMS in data.errors of that sub-call |
personalPhoto: nullrefused 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.