For AI agents: markdown of this page — /docs-content-en/entities/leads.md documentation index — /llms.txt
Leads
CRM lead management: create, retrieve, update, delete, filter.
Bitrix24 API: crm.item.*
Scope: crm
A lead can originate from a CRM form. Its ID and fields are available via GET /v1/crm-forms/:id.
Create lead
POST /v1/leads
Creates a new lead in CRM.
Request fields (body)
| Parameter | Type | Description |
|---|---|---|
Parametertitle |
Typestring | DescriptionLead title |
Parametername |
Typestring | DescriptionContact first name |
ParameterlastName |
Typestring | DescriptionContact last name |
ParametersecondName |
Typestring | DescriptionMiddle name |
ParameterstageId |
Typestring | DescriptionLead status — canonical name, the statusId alias is also accepted. Standard statuses: NEW, IN_PROCESS, PROCESSED. A Bitrix24 account may have its own — list: GET /v1/statuses?filter[entityId]=STATUS. In the response the value is returned in the stageId field. Before writing, the value is matched exactly against the status dictionary — a status that does not exist is rejected with UNKNOWN_STAGE, and no record is created. An empty value is not checked: the lead gets the default status |
Parameteropportunity |
Typenumber | DescriptionAmount — canonical name, the amount alias is also accepted. Important: for the value to persist, pass isManualOpportunity: true in the same request — otherwise Bitrix24 recalculates the amount from the product rows |
ParameterisManualOpportunity |
Typeboolean | DescriptionManual amount mode (see opportunity) |
Parametercurrency |
Typestring | DescriptionCurrency (alias currencyId). List: GET /v1/currencies |
ParametercompanyTitle |
Typestring | DescriptionCompany name (text, not ID) |
Parameterphone |
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" }] |
Parameteremail |
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" }] |
Parameterpost |
Typestring | DescriptionPosition |
Parametercomments |
Typestring | DescriptionComment |
ParametersourceId |
Typestring | DescriptionSource. List: GET /v1/statuses?filter[entityId]=SOURCE |
ParametersourceDescription |
Typestring | DescriptionSource description |
ParameterassignedById |
Typenumber | DescriptionAssignee. List: GET /v1/users |
Parameteropened |
Typeboolean | DescriptionAvailable to everyone |
ParameterufCrm* |
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 201, so map the label to its ID on your side and check the stored value of this field in the response data |
Full list of fields: GET /v1/leads/fields.
Examples
curl — personal key
curl -X POST https://vibecode.bitrix24.com/v1/leads \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Website request",
"name": "Maria",
"lastName": "Davis",
"phone": "+12025550123",
"sourceId": "WEB",
"stageId": "NEW"
}'
curl — OAuth application
curl -X POST https://vibecode.bitrix24.com/v1/leads \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Website request",
"name": "Maria",
"lastName": "Davis",
"phone": "+12025550124",
"sourceId": "WEB",
"stageId": "NEW"
}'
JavaScript — personal key
const res = await fetch('https://vibecode.bitrix24.com/v1/leads', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'Website request',
name: 'Maria',
lastName: 'Davis',
phone: '+12025550125',
sourceId: 'WEB',
stageId: 'NEW',
}),
})
const { success, data } = await res.json()
console.log('Lead ID:', data.id)
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/leads', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'Website request',
name: 'Maria',
lastName: 'Davis',
phone: '+12025550126',
sourceId: 'WEB',
stageId: 'NEW',
}),
})
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": "+12025550127", "typeId": "WORK" },
{ "value": "+12025550123", "typeId": "MOBILE" }
],
"email": [
{ "value": "work@example.com", "typeId": "WORK" },
{ "value": "personal@example.com", "typeId": "HOME" }
]
}
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | Descriptiontrue on successful creation |
Fielddata |
Typeobject | DescriptionThe created lead. Full list of fields — Lead fields |
Fielddata.id |
Typenumber | DescriptionID of the created lead |
Fielddata.title |
Typestring | DescriptionTitle |
Fielddata.stageId |
Typestring | DescriptionLead status |
Fielddata.assignedById |
Typenumber | DescriptionAssignee |
Fielddata.createdBy |
Typenumber | DescriptionCreator |
Fielddata.createdTime |
Typedatetime | DescriptionCreation date |
The lead card URL in Bitrix24 is built from data.id:
https://<portal>.bitrix24.com/crm/lead/details/<id>/
<portal> — the Bitrix24 portal domain. Access is limited by the employee's permissions in Bitrix24.
Response example
{
"success": true,
"data": {
"id": 5001,
"title": "Website request",
"stageId": "NEW",
"assignedById": 1,
"createdBy": 1,
"createdTime": "2026-04-15T13:00:00+00:00",
"updatedTime": "2026-04-15T13:00:00+00:00",
"opened": true,
"sourceId": "WEB"
}
}
Error response example
403 — no scope:
{
"success": false,
"error": {
"code": "SCOPE_DENIED",
"message": "This endpoint requires 'crm' scope"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP403 | CodeSCOPE_DENIED |
DescriptionThe API key does not have the crm scope |
| HTTP401 | CodeTOKEN_MISSING |
DescriptionThe API key has no configured tokens |
| HTTP400 | CodeINVALID_MULTIFIELD_SHAPE |
DescriptionWrong shape for phone or email — the expected shape is [{ "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. There is nothing to address on create: Bitrix24 assigns multifield row IDs itself, 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": {…}}}) |
| HTTP400 | CodeREADONLY_FIELD |
DescriptionAttempt to write a read-only field |
| HTTP400 | CodeUNKNOWN_STAGE |
DescriptionstageId / statusId is not in the lead status dictionary (STATUS): a typo, wrong letter case, or a deal stage instead of a lead status. No record is created; message suggests the exact spelling, details.knownStages lists the dictionary's statuses |
Full list of common API errors — Errors.
Known specifics
Simple CRM mode (no leads): when the Bitrix24 account runs CRM in simple mode, Bitrix24 converts the lead right on creation — it comes back CONVERTED and closed, with a contact and a deal created from it that the request never asked for. The requested stage is not kept. Vibecode changes nothing in the request: this is Bitrix24's own behavior, and the mode cannot be switched through the API — only in the CRM settings. The response stays 201, and meta.warnings gets a LEAD_AUTO_CONVERTED warning with the IDs of the contact (contactId) and deal (dealId) Bitrix24 created; null when the record was not created or not found: a contact you linked yourself via contactId is reused by Bitrix24 and does not count as created. There is no warning when CONVERTED was requested explicitly. On such an account, create deals and contacts directly.
Lead conversion: Bitrix24 REST has no dedicated conversion method. To "convert" a lead, create a deal/contact/company with leadId and update the lead status:
// 1. Create a deal from the lead
await fetch('/v1/deals', { body: { title: 'From lead', leadId: 5001 } })
// 2. Close the lead
await fetch('/v1/leads/5001', { method: 'PATCH', body: { statusId: 'CONVERTED' } })