For AI agents: markdown of this page — /docs-content-en/entities/leads/update.md documentation index — /llms.txt
Update lead
PATCH /v1/leads/:id
Updates the fields of an existing lead. Pass only the fields you want to change. See the full list in the field reference.
Important note on
phone(multifield): On update, Bitrix24 only adds new multifield records. A PATCH with{"email": "new@y.com"}to a lead that already has an email will not replace the old one — the lead will end up with two emails. This is Bitrix24-specific behavior, not Vibecode's. To replace or remove an email/phone, edit the lead in the Bitrix24 UI. An object with anidfield (an attempt to update or delete a single row) is not accepted by this PATCH:400 MULTIFIELD_ID_NOT_SUPPORTED, and nothing is written. An object keyed by row ids ({"fm": {"11": {…}}}, or the same shape inphone/400 MULTIFIELD_ID_NOT_SUPPORTED. The rawfmis accepted only as an array.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
Parameterid (path) |
Typenumber | Requiredyes | DescriptionLead ID. List: GET /v1/leads |
Request fields (body)
| Field | Type | Description |
|---|---|---|
FieldstageId |
Typestring | DescriptionLead status — canonical name, the statusId alias is also accepted. List: GET /v1/statuses?filter[entityId]=STATUS. In the response the value is returned in the stageId field |
Fieldopportunity |
Typenumber | DescriptionAmount — canonical name, the amount alias is also accepted. Important: for the value to persist, pass isManualOpportunity: true in the same request |
FieldassignedById |
Typenumber | DescriptionAssignee. List: GET /v1/users |
Fieldtitle |
Typestring | DescriptionLead title |
Fieldphone |
Typestring | string[] | object[] | DescriptionPhone. Accepts three forms: a string "+1...", an array of strings ["+1...", "+1..."], or an array of objects [{ "value": "+1...", "typeId": "WORK" }, …]. typeId: WORK | HOME | MOBILE | OTHER (default WORK). Important: the UPPER form [{ "VALUE": "...", "VALUE_TYPE": "WORK" }] is not accepted — it returns 400 INVALID_MULTIFIELD_SHAPE. Use camelCase: [{ "value": "...", "typeId": "WORK" }] |
Fieldemail |
Typestring | string[] | object[] | DescriptionEmail. Accepts three forms: a string "a@b.com", an array of strings ["a@b.com", "b@c.com"], or an array of objects [{ "value": "a@b.com", "typeId": "WORK" }, …]. typeId: WORK | HOME | MAILING | OTHER (default WORK). Important: the UPPER form [{ "VALUE": "...", "VALUE_TYPE": "WORK" }] is not accepted — it returns 400 INVALID_MULTIFIELD_SHAPE. Use camelCase: [{ "value": "...", "typeId": "WORK" }] |
FieldufCrm* |
Typeper field schema | DescriptionA user field of the Bitrix24 account, for example ufCrmProjectCode. The actual name and type are in the schema GET /v1/leads/fields, and the value format for each type is in User fields (UF). An enumeration field takes the option ID from the field's items array in the schema, and a multiple field takes an array of such IDs. If you send the option label VALUE instead of the ID, the value is lost: a single-value field gets 0. A number that is not among the options is stored as is. Neither the label nor a non-existent ID raises an error, and the request returns 200, so map the label to its ID on your side and check the stored value of this field in the response data |
Examples
curl — personal key
curl -X PATCH "https://vibecode.bitrix24.com/v1/leads/42" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"stageId": "IN_PROCESS",
"opportunity": 2500,
"isManualOpportunity": true,
"assignedById": 3,
"title": "Website request — hot lead"
}'
curl — OAuth application
curl -X PATCH "https://vibecode.bitrix24.com/v1/leads/42" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"stageId": "IN_PROCESS",
"opportunity": 2500,
"isManualOpportunity": true,
"assignedById": 3,
"title": "Website request — hot lead"
}'
JavaScript — personal key
const res = await fetch('https://vibecode.bitrix24.com/v1/leads/42', {
method: 'PATCH',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
stageId: 'IN_PROCESS',
opportunity: 2500,
isManualOpportunity: true,
assignedById: 3,
title: 'Website request — hot lead',
}),
})
const { success, data } = await res.json()
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/leads/42', {
method: 'PATCH',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
stageId: 'IN_PROCESS',
opportunity: 2500,
isManualOpportunity: true,
assignedById: 3,
title: 'Website request — hot lead',
}),
})
const { success, data } = await res.json()
Alternative form — array of objects with explicit `typeId`
If you need to specify multiple values or an explicit type (HOME, MOBILE):
{
"phone": [
{ "value": "+12025550123", "typeId": "WORK" },
{ "value": "+12025550124", "typeId": "MOBILE" }
],
"email": [
{ "value": "work@example.com", "typeId": "WORK" },
{ "value": "personal@example.com", "typeId": "HOME" }
]
}
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | Descriptiontrue when the lead is updated |
Fielddata |
Typeobject | DescriptionThe updated lead object with all fields — see Fields |
Response example
{
"success": true,
"data": {
"id": 42,
"title": "Website request",
"stageId": "IN_PROCESS",
"assignedById": 1,
"createdTime": "2026-04-15T12:00:00+00:00",
"updatedTime": "2026-04-15T13:00:00+00:00"
}
}
Error response example
404 — lead not found:
{
"success": false,
"error": {
"code": "ENTITY_NOT_FOUND",
"message": "Item not found"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP404 | CodeENTITY_NOT_FOUND |
DescriptionLead not found |
| HTTP422 | CodeSTAGE_NOT_APPLIED |
DescriptionThe stageId or statusId you sent was not applied: after the PATCH the status remained unchanged, for example when the value is not in the dictionary. Details are in error.message and error.details, the re-read lead is in data. The record has already been changed and the other fields of the body may have been applied: correct the value and send only what still needs changing, not the whole body again |
| HTTP403 | CodeACCESS_DENIED |
DescriptionNo access |
| HTTP400 | CodeINVALID_MULTIFIELD_SHAPE |
DescriptionWrong shape for phone or email — expects [{ "value", "typeId" }]. The same code is returned when phone or email holds an object without value — for example empty or with keys such as n0, 0 or 011 — or a number or true/false, on its own or as an array item, or when the raw fm is not an array, for example a string, a number, an empty object or an object keyed by type such as PHONE: fm is accepted only as an array [{ "typeId", "valueType", "value" }]. The request is refused and nothing is written |
| HTTP400 | CodeMULTIFIELD_ID_NOT_SUPPORTED |
Descriptionphone, email or the raw fm[] contains an object with an id field. Bitrix24 neither updates nor deletes a single multifield row through this call — it would append a duplicate — so the request is refused and nothing is written. The same refusal applies when fm, phone or email is sent as an object keyed by row ids ({"fm": {"11": {…}}}): updating or deleting a single multifield row by id through the API is not possible |
| HTTP400 | CodeREADONLY_FIELD |
DescriptionAttempt to write a read-only field |
| HTTP403 | CodeSCOPE_DENIED |
DescriptionThe API key does not have the crm scope |
| HTTP401 | CodeTOKEN_MISSING |
DescriptionThe API key has no configured tokens |
Full list of common API errors — Errors.