{% note tip "" %}
Choose a tool for developing with an AI agent:
- use Alaio Vibecode to build an app for Bitrix24 from a task description without knowing any programming language. The agent writes the code and deploys the app to a server, with no manual hosting setup
- use the MCP server to develop a REST API integration in your own project. The agent refers to the official REST documentation
{% endnote %}
Scope:
user.userfieldWho can execute the method: administrator
The user.userfield.add method adds a custom field.
{% include Note on required parameters %}
#|
|| Name
type | Description ||
|| fields*
object| Field values for adding a new custom field ||
|#
{% include Note on required parameters %}
#|
|| Name
type | Description ||
|| FIELD_NAME*
string| Field name (code). Bitrix24 converts it to uppercase and supplements it with the UF_USR_ prefix:
DEALSandUF_DEALSbecomeUF_USR_DEALSUF_USR_DEALSremains unchanged
The resulting field code is returned by the user.userfield.list method ||
|| USER_TYPE_ID*
string| Custom field type. Possible values:
string— stringinteger— integerdouble— numberdate— datedatetime— date with timeboolean— Yes / Nofile— fileenumeration— listurl— linkaddress— Google Maps addressmoney— moneyiblock_section— Link to infoblock sectioniblock_element— Link to infoblock itememployee— Link to usercrm— Link to CRM itemcrm_status— Link to CRM directory || || XML_IDstring| External code || || SORTinteger| Sort order || || MULTIPLEboolean| Whether the field is multiple. Possible values:Y— yesN— no || || MANDATORYboolean| Whether the custom field is required. Possible values:Y— yesN— no || || SHOW_FILTERboolean| Whether to show the field in the list filter. Possible values:Y— yesN— no || || SHOW_IN_LISTboolean| Whether to show the field in the list. Possible values:Y— yesN— no ||- || EDIT_IN_LIST
boolean| Whether to edit the field in the list. Possible values: Y— yesN— no ||- || IS_SEARCHABLE
boolean| Whether the field is included in search. Possible values: Y— yesN— no || || SETTINGSobject| An object in{"field_1": "value_1", ... "field_N": "value_N"}format to pass additional custom field settings. Settings are described below || || EDIT_FORM_LABELstring| Label in the editing form. You can pass a string or an object with labels by language in{"de": "...", "en": "..."}format. If a string is passed, the value will be set for all languages || || LIST_COLUMN_LABELstring| Column header in the list. You can pass a string or an object with labels by language in{"de": "...", "en": "..."}format. If a string is passed, the value will be set for all languages || || LIST_FILTER_LABELstring| Filter header in the list. You can pass a string or an object with labels by language in{"de": "...", "en": "..."}format. If a string is passed, the value will be set for all languages || || ERROR_MESSAGEstring| Error message for invalid input. You can pass a string or an object with texts by language in{"de": "...", "en": "..."}format. If a string is passed, the value will be set for all languages || || HELP_MESSAGEstring| Tooltip text for the field. You can pass a string or an object with texts by language in{"de": "...", "en": "..."}format. If a string is passed, the value will be set for all languages || || LABELstring| Default custom field name.
The value will be set in fields LIST_FILTER_LABEL, LIST_COLUMN_LABEL, EDIT_FORM_LABEL, ERROR_MESSAGE, HELP_MESSAGE if no value is provided in them ||
|#
Each custom field type has its own set of additional configurations.
{% list tabs %}
-
string
#| || Name
type| Description || || DEFAULT_VALUEstring| Default value.Default
''|| || ROWSinteger| Number of lines in the input field. Must be greater than 0.Default
1|| |# -
integer
#| || Name
type| Description || || DEFAULT_VALUEinteger| Default value || |# -
double
#| || Name
type| Description || || DEFAULT_VALUEdouble| Default value || || PRECISIONinteger| Number precision. Must be greater than or equal to 0.Default
2|| |# -
boolean
#| || Name
type| Description || || DEFAULT_VALUEinteger| Default value, where1is yes,0is no.Possible values:
>= 1-> 1<= 0-> 0
Default
0|| || DISPLAYstring| Appearance. Possible values:CHECKBOX— checkboxRADIO— radio buttonsDROPDOWN— dropdown list
Default
CHECKBOX|| |# -
date|datetime
#| || Name
type| Description || || DEFAULT_VALUEobject| Default value.Object format:
{ VALUE: datetime|date, TYPE: 'NONE'|'NOW'|'FIXED', }where:
VALUE— default value of typedatetimeordateTYPE— type of the default value:NONE— do not set a default valueNOW— use current time/dateFIXED— use time/date fromVALUE
Default value:
{ VALUE: '', TYPE: 'NONE', }|| |#
-
enumeration
#| || Name
type| Description || || DISPLAYstring| Appearance. Possible values:LIST— listUI— editable listCHECKBOX— checkboxesDIALOG— entity selection dialog
Default
LIST|| || LIST_HEIGHT | List height. Must be greater than 0.Available only when
DISPLAY = LISTorDISPLAY = UI.Default
1|| |# -
iblock_section|iblock_element
#| || Name
type| Description || || IBLOCK_TYPE_IDstring| Infoblock type identifier.Default
''|| || IBLOCK_IDstring| Information block identifier.Default
0|| || DEFAULT_VALUEstring| Default value.Default
''|| || DISPLAYstring| Appearance. Possible values:DIALOG— dialogUI— editable listLIST— listCHECKBOX— checkboxes
Default
LIST|| || LIST_HEIGHTinteger| List height. Must be greater than 0.Default
1|| || ACTIVE_FILTERboolean| Whether to show items with the activity flag enabled. Possible values:Y— yesN— no
Default is
N|| |# -
crm_status
#| || Name
type| Description || || ENTITY_TYPEstring| Directory type identifier.Use
crm.status.entity.typesto find possible values.Default
''|| |# -
crm
If none of the following options are passed, linking to leads (
LEAD = Y) will be enabled by default.#| || Name
type| Description || || LEADboolean| Whether binding to Leads is enabled. Possible values:Y— yesN— no
Default is
N|| || CONTACTboolean| Whether binding to Contacts is enabled. Possible values:Y— yesN— no
Default is
N|| || COMPANYboolean| Whether binding to Companies is enabled. Possible values:Y— yesN— no
Default is
N|| || DEALboolean| Whether binding to Deals is enabled. Possible values:Y— yesN— no
Default is
N|| |# -
Python
from b24pysdk.errors import BitrixAPIError, BitrixSDKException fields = { "FIELD_NAME": "UF_USR_SKILLS_PROFILE", "USER_TYPE_ID": "string", "XML_ID": "UF_USR_SKILLS_PROFILE", "SORT": 150, "MULTIPLE": "N", "MANDATORY": "N", "SHOW_FILTER": "Y", "SHOW_IN_LIST": "Y", "EDIT_IN_LIST": "Y", "IS_SEARCHABLE": "Y", "SETTINGS": { "DEFAULT_VALUE": "Python integration engineer", "ROWS": 3, }, "EDIT_FORM_LABEL": { "en": "Skills profile", }, "LIST_COLUMN_LABEL": { "en": "Skills profile", }, "LIST_FILTER_LABEL": { "en": "Skills profile", }, "ERROR_MESSAGE": { "en": "Skills profile is invalid", }, "HELP_MESSAGE": { "en": "Store a short integration skills summary.", }, "LABEL": "Skills profile", } try: bitrix_response = client.user.userfield.add( fields=fields, ).response result = bitrix_response.result print(result) except BitrixAPIError as error: print( "Bitrix API Error", f"error: {error.error}", f"error_description: {error.error_description}", sep="\n", ) except BitrixSDKException as error: print("Bitrix SDK error", error.message, sep="\n") except Exception as error: print("Unexpected error", error, sep="\n")
{% endlist %}
{% note info "" %}
If it is necessary to create a custom field with an added custom type via the API, you must specify rest_<app_number>_<added_type_USER_TYPE_ID> in the USER_TYPE_ID field. For example, rest_436278_test_type.
{% endnote %}
{% include Note on examples %}
{% list tabs %}
-
cURL (Webhook)
curl -X POST \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{"fields": { "FIELD_NAME": "UF_USR_DEALS", "USER_TYPE_ID": "crm", "XML_ID": "UF_CRM_DEALS", "SORT": 100, "MULTIPLE": "Y", "MANDATORY": "N", "SHOW_FILTER": "N", "SHOW_IN_LIST": "Y", "EDIT_IN_LIST": "Y", "SETTINGS": { "DEAL": "Y" }, "LABEL": "CRM Deal Linking", "EDIT_FORM_LABEL": { "de": "CRM Deal Linking" } } }' \ https://**put_your_bitrix24_address**/rest/**put_your_user_id_here**/**put_your_webhook_here**/user.userfield.add
-
cURL (OAuth)
curl -X POST \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{"fields": { "FIELD_NAME": "UF_USR_DEALS", "USER_TYPE_ID": "crm", "XML_ID": "UF_CRM_DEALS", "SORT": 100, "MULTIPLE": "Y", "MANDATORY": "N", "SHOW_FILTER": "N", "SHOW_IN_LIST": "Y", "EDIT_IN_LIST": "Y", "SETTINGS": { "DEAL": "Y" }, "LABEL": "CRM Deal Linking", "EDIT_FORM_LABEL": { "de": "CRM Deal Linking" } }, "auth": "**put_access_token_here**" }' \ https://**put_your_bitrix24_address**/rest/user.userfield.add
-
JS (TS)
// This snippet is an ES module: top-level await requires type="module" or a bundler. // $b24 is an already-initialized SDK instance (see the SDK "Get started" guide). import { Text } from '@bitrix24/b24jssdk' import type { B24Frame } from '@bitrix24/b24jssdk' declare const $b24: B24Frame // Shape of the payload returned in result (match the "response handling" section of the page) type AddUserFieldResult = number try { const response = await $b24.actions.v2.call.make<AddUserFieldResult>({ method: 'user.userfield.add', params: { fields: { FIELD_NAME: 'UF_USR_DEALS', USER_TYPE_ID: 'crm', XML_ID: 'UF_CRM_DEALS', SORT: 100, MULTIPLE: 'Y', MANDATORY: 'N', SHOW_FILTER: 'N', SHOW_IN_LIST: 'Y', EDIT_IN_LIST: 'Y', SETTINGS: { DEAL: 'Y', }, LABEL: 'CRM deals binding', EDIT_FORM_LABEL: { ru: 'CRM deals binding', }, }, }, requestId: Text.getUuidRfc4122() }) // The payload is available only on a successful response if (!response.isSuccess) { console.error(response.getErrorMessages().join('; ')) } else { const result = response.getData()!.result console.info('Created user field with ID:', result) } } catch (error) { // Thrown on transport or SDK failures (AjaxError, SdkError, etc.) console.error(error) }
-
JS (UMD)
<!-- Load the SDK (UMD build); it is exposed as the global B24Js --> <script src="https://unpkg.com/@bitrix24/b24jssdk@1/dist/umd/index.min.js"></script> <script> async function addUserField() { try { // Initialize the SDK inside a Bitrix24 frame const $b24 = await B24Js.initializeB24Frame() const response = await $b24.actions.v2.call.make({ method: 'user.userfield.add', params: { fields: { FIELD_NAME: 'UF_USR_DEALS', USER_TYPE_ID: 'crm', XML_ID: 'UF_CRM_DEALS', SORT: 100, MULTIPLE: 'Y', MANDATORY: 'N', SHOW_FILTER: 'N', SHOW_IN_LIST: 'Y', EDIT_IN_LIST: 'Y', SETTINGS: { DEAL: 'Y', }, LABEL: 'CRM deals binding', EDIT_FORM_LABEL: { ru: 'CRM deals binding', }, }, }, requestId: B24Js.Text.getUuidRfc4122() }) // The payload is available only on a successful response if (!response.isSuccess) { console.error(response.getErrorMessages().join('; ')) return } const result = response.getData().result console.info('Created user field with ID:', result) } catch (error) { // Thrown on transport or SDK failures (AjaxError, SdkError, etc.) console.error(error) } } document.addEventListener('DOMContentLoaded', addUserField) </script>
-
Python
from b24pysdk.errors import BitrixAPIError, BitrixSDKException try: bitrix_response = client.user.userfield.add( fields={ "FIELD_NAME": "UF_USER_DEALS", "USER_TYPE_ID": "crm", "XML_ID": "UF_CRM_DEALS", "SORT": 100, "MULTIPLE": "Y", "MANDATORY": "N", "SHOW_FILTER": "N", "SHOW_IN_LIST": "Y", "EDIT_IN_LIST": "Y", "SETTINGS": { "DEAL": "Y", }, "LABEL": "Linking to CRM deals", "EDIT_FORM_LABEL": { "ru": "Linking to CRM deals", }, }, ).response result = bitrix_response.result print(result) except BitrixAPIError as error: print( "Bitrix API error", f"error: {error.error}", f"error_description: {error.error_description}", sep="\n", ) except BitrixSDKException as error: print(f"Bitrix SDK error: {error.message}") except Exception as error: print(f"Unexpected error: {error}")
-
PHP
try { $response = $b24Service ->core ->call( 'user.userfield.add', [ 'fields' => [ 'FIELD_NAME' => 'UF_USR_DEALS', 'USER_TYPE_ID' => 'crm', 'XML_ID' => 'UF_CRM_DEALS', 'SORT' => 100, 'MULTIPLE' => 'Y', 'MANDATORY' => 'N', 'SHOW_FILTER' => 'N', 'SHOW_IN_LIST' => 'Y', 'EDIT_IN_LIST' => 'Y', 'SETTINGS' => [ 'DEAL' => 'Y', ], 'LABEL' => 'CRM Deal Linking', 'EDIT_FORM_LABEL' => [ 'de' => 'CRM Deal Linking' ], ] ] ); $result = $response ->getResponseData() ->getResult(); echo 'Success: ' . print_r($result, true); processData($result); } catch (Throwable $e) { error_log($e->getMessage()); echo 'Error adding user field: ' . $e->getMessage(); }
-
BX24.js
BX24.callMethod( 'user.userfield.add', { fields: { FIELD_NAME: "UF_USR_DEALS", USER_TYPE_ID: "crm", XML_ID: "UF_CRM_DEALS", SORT: 100, MULTIPLE: "Y", MANDATORY: "N", SHOW_FILTER: "N", SHOW_IN_LIST: "Y", EDIT_IN_LIST: "Y", SETTINGS: { DEAL: "Y", }, LABEL: "CRM Deal Linking", EDIT_FORM_LABEL: { ru: "CRM Deal Linking" }, }, }, function(result) { if(result.error()) console.error(result.error()); else console.log(result.data()); } );
-
PHP CRest
require_once('crest.php'); $result = CRest::call( 'user.userfield.add', [ 'fields' => [ 'FIELD_NAME' => 'UF_USR_DEALS', 'USER_TYPE_ID' => 'crm', 'XML_ID' => 'UF_CRM_DEALS', 'SORT' => 100, 'MULTIPLE' => 'Y', 'MANDATORY' => 'N', 'SHOW_FILTER' => 'N', 'SHOW_IN_LIST' => 'Y', 'EDIT_IN_LIST' => 'Y', 'SETTINGS' => [ 'DEAL' => 'Y', ], 'LABEL' => 'CRM Deal Linking', 'EDIT_FORM_LABEL' => [ 'de' => 'CRM Deal Linking' ], ] ] ); echo '<PRE>'; print_r($result); echo '</PRE>';
-
Go
// client and ctx are already created — see the Go SDK section res, err := client.Core().Call(ctx, "user.userfield.add", b24.Params{ "fields": b24.Params{ "FIELD_NAME": "UF_USR_DEALS", "USER_TYPE_ID": "crm", "XML_ID": "UF_CRM_DEALS", "SORT": 100, "MULTIPLE": "Y", "MANDATORY": "N", "SHOW_FILTER": "N", "SHOW_IN_LIST": "Y", "EDIT_IN_LIST": "Y", "SETTINGS": b24.Params{ "DEAL": "Y", }, "LABEL": "CRM Deal Linking", "EDIT_FORM_LABEL": b24.Params{ }, }, }) if err != nil { return fmt.Errorf("user.userfield.add: %w", err) } var newID b24.ID if err := json.Unmarshal(res.Result, &newID); err != nil { return fmt.Errorf("parse response: %w", err) } fmt.Println("id:", newID)
{% endlist %}
HTTP status: 200
{
"result":177,
"time":{
"start":1747301035.550121,
"finish":1747301037.514112,
"duration":1.9639909267425537,
"processing":0.5865437984466553,
"date_start":"2025-05-15T11:23:55+02:00",
"date_finish":"2025-05-15T11:23:57+02:00",
"operating":0
}
}#|
|| Name
type | Description ||
|| result
integer | Identifier of the created custom field ||
|| time
time | Request execution time information ||
|#
HTTP status: 400
{
"error":"",
"error_description":"The \u0027FIELD_NAME\u0027 field is not found."
}{% include notitle Error handling %}
#|
|| Code | Description | Value ||
|| ERROR_ARGUMENT | Argument 'USER_TYPE_ID' is null or empty | Not specified USER_TYPE_ID ||
|| ERROR_ARGUMENT | Argument 'HANDLER' is null or empty | Not specified HANDLER ||
|| ERROR_CORE | Field *** for USER object already exists | Field *** for USER object already exists ||
|| ERROR_CORE | Fail to create new user field | Error while creating field ||
|| Empty string | The \u0027FIELD_NAME\u0027 field is not found. | Mandatory field FIELD_NAME is not specified ||
|| Empty string | The \u0027USER_TYPE_ID\u0027 field is not found. | Mandatory field USER_TYPE_ID is not specified ||
|#
{% include System errors %}