For AI agents: markdown of this page — /docs-content-en/entities/leads/contacts.md documentation index — /llms.txt

Lead contacts

Links contacts to a lead, replaces the set of linked contacts, reads the list, and unlinks contacts one at a time or all at once. A link stores the contact's position in the list and the primary-contact flag. Unlinked contacts stay in the CRM.

A lead with contacts always has exactly one primary contact. Its ID arrives in the lead's contactId field, and the IDs of all linked contacts arrive in the contactIds field. Change the set of contacts with the methods below: PATCH /v1/leads/:id with these fields replaces the whole set and can unlink the other contacts.

Bitrix24 API: crm.lead.contact.items.get, crm.lead.contact.add, crm.lead.contact.items.set, crm.lead.contact.delete, crm.lead.contact.items.delete Scope: crm

List lead contacts

GET /v1/leads/:id/contacts

Returns the links between a lead and its contacts: contact ID, position, and primary flag, so you know who is linked before changing the set of contacts.

Parameters

Parameter Type Required Description
Parameterid (path) Typenumber Requiredyes DescriptionLead ID. List: GET /v1/leads

There is no pagination: the response contains all of the lead's links in one call.

Examples

curl — personal key

Terminal
curl "https://vibecode.bitrix24.com/v1/leads/1001321/contacts" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl "https://vibecode.bitrix24.com/v1/leads/1001321/contacts" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/leads/1001321/contacts', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data } = await res.json()
const primary = data.find((link) => link.isPrimary)
console.log('Primary contact:', primary?.contactId)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/leads/1001321/contacts', {
  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 success
Fielddata Typearray DescriptionLinks between the lead and its contacts, in sort order. An empty array for a lead without contacts and for a lead that does not exist
Fielddata[].contactId Typenumber DescriptionContact ID. Get the contact: GET /v1/contacts/:id
Fielddata[].isPrimary Typeboolean DescriptionPrimary contact of the lead. For a lead with contacts, true on exactly one link
Fielddata[].sort Typenumber DescriptionPosition of the contact in the list
Fielddata[].roleId Typenumber DescriptionRole of the contact in the lead. The link methods do not store it

Response example

JSON
{
  "success": true,
  "data": [
    { "contactId": 2937, "sort": 10, "isPrimary": false, "roleId": 0 },
    { "contactId": 2939, "sort": 20, "isPrimary": true, "roleId": 0 },
    { "contactId": 2941, "sort": 30, "isPrimary": false, "roleId": 0 }
  ]
}

Error response example

400 — id is not a positive integer:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "id must be a positive integer"
  }
}

Errors

HTTP Code Description
HTTP400 CodeINVALID_PARAMS Descriptionid is not a positive integer, for example abc or 0
HTTP401 CodeMISSING_API_KEY DescriptionThe X-Api-Key header is missing
HTTP401 CodeTOKEN_MISSING DescriptionThe key has no Bitrix24 tokens attached
HTTP403 CodeSCOPE_DENIED DescriptionThe key does not have the crm scope
HTTP429 CodeRATE_LIMITED DescriptionRate limit exceeded: 300 requests per minute per portal, all API keys of the portal share one limit. The exact value arrives in the x-ratelimit-limit header (the cap is divided across replicas). Retry after the delay in the Retry-After header
HTTP502 CodeBITRIX_UNAVAILABLE DescriptionBitrix24 is unavailable. Retry the request later

Full list of common API errors — Errors.

Known specifics

  • An empty list does not prove the lead exists. For a deleted lead and for an ID that never existed, the response is the same as for a lead without contacts. Check that the lead exists with GET /v1/leads/:id: it responds with 404 for a missing lead.
  • An ID in the list may not point to a contact. Linking does not check the contact ID, so the list can contain an ID that matches no contact. Before working with a contact, request it with GET /v1/contacts/:id.
  • Contacts together with the lead. GET /v1/leads/:id?include=contactBinding returns the lead and the full records of the linked contacts in data._included.contactBindings. With include=contact, data._included.contact carries a single object — the primary contact. The primary contact's ID is returned in the lead's contactId field, and the IDs of all linked contacts in contactIds.

See also