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

Contact companies

Links companies to a contact, replaces the whole set, reads the list, and unlinks companies one at a time or all at once. A binding stores the company's position in the list and the primary-company flag. Unlinked companies stay in the CRM.

A contact with companies always has one primary company. Its ID arrives in the contact's companyId field, and the IDs of all linked companies arrive in the companyIds field in sort order. The companyIds field is writable: PATCH /v1/contacts/:id with it replaces the whole set of companies, the same way as PUT /v1/contacts/:id/companies. Companies missing from the array are unlinked.

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

List contact companies

GET /v1/contacts/:id/companies

Returns all companies linked to a contact, so you know the current set before linking, replacing, or unlinking.

Parameters

Parameter Type Required Description
id (path) number yes Contact ID. List: GET /v1/contacts

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

Examples

curl — personal key

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

curl — OAuth application

Terminal
curl "https://vibecode.bitrix24.com/v1/contacts/2943/companies" \
  -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/contacts/2943/companies', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

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

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/contacts/2943/companies', {
  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 success
data array The contact's company bindings in sort order. For a contact without companies — an empty array
data[].companyId number Company ID. Get the company: GET /v1/companies/:id
data[].isPrimary boolean The contact's primary company. For a contact with companies, true on exactly one binding
data[].sort number The company's position in the list
data[].roleId number Binding role. The binding methods do not save it

Response example

JSON
{
  "success": true,
  "data": [
    { "companyId": 3099, "sort": 10, "isPrimary": false, "roleId": 0 },
    { "companyId": 3101, "sort": 20, "isPrimary": true, "roleId": 0 },
    { "companyId": 3103, "sort": 30, "isPrimary": false, "roleId": 0 }
  ]
}

Error response example

400 — id in the path is not a positive integer:

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

Errors

HTTP Code Description
400 INVALID_PARAMS id is not a positive integer, for example abc
401 MISSING_API_KEY The X-Api-Key header is missing
401 TOKEN_MISSING No Bitrix24 tokens are attached to the key
403 SCOPE_DENIED The key lacks the crm scope
429 RATE_LIMITED Rate 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
502 BITRIX_UNAVAILABLE Bitrix24 is unavailable. Retry the request later

Full list of common API errors — Errors.

Known specifics

  • An empty list for a nonexistent contact too. For an ID that does not belong to any contact, the method returns 200 with an empty data, as for a contact without companies. To tell these cases apart, request the contact with GET /v1/contacts/:id: for a nonexistent contact it returns 404 ENTITY_NOT_FOUND.
  • An ID in the list might not point to an existing company. Linking does not check the company ID, so the list can contain an ID that does not belong to any company. Before working with a company, request it with GET /v1/companies/:id.
  • Companies together with the contact. GET /v1/contacts/:id?include=companyBinding returns the contact and the full records of all linked companies in data._included.companyBindings; with include=company, only the primary company in data._included.company. The primary company's ID arrives in the contact field companyId, and the IDs of all linked companies in companyIds.

See also