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

Create employee

POST /v1/users

Creates a new employee in the Bitrix24 account. The minimum required field is email. Returns the ID and the full record of the just-created employee.

For integrations with user input, POST /v1/users/invite is more convenient: it validates email on the Vibecode side (EMAIL_REQUIRED, EMAIL_INVALID) and automatically sets departmentId: [1] for intranet employees. This endpoint is the low-level form; errors are propagated from Bitrix24 as-is.

Request fields (body)

Parameter Type Req. Description
email string yes Email — must be unique across all employees in the Bitrix24 account
name string no First name
lastName string no Last name
secondName string no Middle name
workPosition string no Position
workPhone string no Work phone
personalPhone string no Personal phone
personalMobile string no Mobile phone
personalBirthday string no Date of birth (ISO 8601)
personalGender string no Gender: M — male, F — female
personalCity string no City
departmentId number[] conditional Array of department IDs. For intranet employees it is required — without it Bitrix24 returns wrong_email. Not used for extranet (EXTRANET: "Y")
xmlId string no External identifier
EXTRANET string no "Y" for an extranet user. Then instead of departmentId you need SONET_GROUP_ID (array of workgroup IDs)
SONET_GROUP_ID number[] conditional Array of workgroup IDs — required with EXTRANET: "Y". List: GET /v1/workgroups

Full list — Employee fields. User fields (UF_*) are also accepted.

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/users" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John",
    "lastName": "Brown",
    "email": "john.brown@example.com",
    "workPosition": "Manager",
    "departmentId": [1]
  }'

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/users" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John",
    "lastName": "Brown",
    "email": "john.brown@example.com",
    "workPosition": "Manager",
    "departmentId": [1]
  }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/users', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'John',
    lastName: 'Brown',
    email: 'john.brown@example.com',
    workPosition: 'Manager',
    departmentId: [1],
  }),
})

const { success, data } = await res.json()
console.log('User ID:', data.id)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/users', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'John',
    lastName: 'Brown',
    email: 'john.brown@example.com',
    workPosition: 'Manager',
    departmentId: [1],
  }),
})

const { success, data } = await res.json()

Response fields

Field Type Description
success boolean Always true on success
data.id number ID of the created employee

The response contains the full record with all employee fields — the same format as GET /v1/users/:id.

The employee card URL in Bitrix24 is built from id:

https://<portal>.bitrix24.com/company/personal/user/<id>/

<portal> — the Bitrix24 account domain. Access is restricted by the employee's rights in Bitrix24.

Response example

JSON
{
  "success": true,
  "data": {
    "id": 1331,
    "xmlId": "74668002",
    "active": true,
    "name": "John",
    "lastName": "Brown",
    "email": "john.brown@example.com",
    "lastLogin": null,
    "dateRegister": "2026-05-06T00:00:00.000Z",
    "isOnline": false,
    "timestampX": {},
    "personalGender": null,
    "personalBirthday": null,
    "departmentId": [1],
    "workPosition": "Manager",
    "userType": "employee"
  }
}

Error response example

400 — email is not passed or duplicates an existing employee:

JSON
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "wrong_email",
    "hint": "Bitrix24 `user.add` returns `wrong_email` for several distinct cases, not only malformed email: (a) the email is already used by ANOTHER Bitrix24 user globally — check with GET /v1/users?filter[EMAIL]=the-email first; (b) the email domain is not allowed by portal policy (some portals restrict external domains); (c) missing UF_DEPARTMENT for intranet users — it is required for intranet invites (try `UF_DEPARTMENT: [1]` for the root department); (d) for external users pass `EXTRANET: \"Y\"` + `SONET_GROUP_ID: [groupId]` instead of UF_DEPARTMENT. For a convenience wrapper, try POST /v1/users/invite which sets sensible defaults. If the email is valid and unused, ask the portal admin to check user-invite settings."
  }
}

Errors

HTTP Code Description
400 BITRIX_ERROR (wrong_email) Email is not passed, duplicates an existing employee, failed the portal domain policy, or departmentId is not specified for an intranet employee
401 TOKEN_MISSING The API key has no configured tokens
403 SCOPE_DENIED The API key lacks the user scope

Full list of common API errors — Errors.

Known specifics

Email must be globally unique. Bitrix24 checks uniqueness across all employees in the Bitrix24 account including previously deactivated ones. Before creation — search via GET /v1/users?filter[EMAIL]=john.brown@example.com. If a record is found and deactivated, bring it back with PATCH /v1/users/:id { active: true } — this preserves the employee's action history and relations, unlike creating a duplicate.

Ambiguity of the wrong_email error. Bitrix24 returns wrong_email for several different situations: email already taken, domain forbidden by Bitrix24 account policy, departmentId not specified for an intranet employee, SONET_GROUP_ID for an external one. The message does not clarify which one. To separate these cases on the Vibecode side, use POST /v1/users/invite — the wrapper returns explicit codes (EMAIL_REQUIRED, EMAIL_INVALID, SONET_GROUP_ID_REQUIRED) before the request to Bitrix24.

See also