Add Service catalog.product.service.add
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
Scope:
catalogWho can execute the method: a user with the "Create product" access permission, one of the "View product catalog", "View catalog products", or "Edit selling price" access permissions, and the permission to edit elements of the catalog information block
The catalog.product.service.add method adds a service to the trade catalog.
Method Parameters
Required parameters are marked with *
|
Name |
Description |
|
fields* |
Field values for creating the service (detailed description) |
Parameter fields
Required parameters are marked with *
|
Name |
Description |
|
iblockId* |
Identifier of the trade catalog information block. You can retrieve the identifier using the catalog.catalog.list method. The variations information block is not suitable: the method returns the |
|
name* |
Service name |
|
active |
Service activity. Possible values:
The method saves any other value as Default is |
|
code |
Symbolic code. The method does not check that the code is unique |
|
xmlId |
External code. Use it to link the service to a record in an external system. If it is not passed, the method writes the service identifier to the field |
|
sort |
Sort order. Default is |
|
createdBy |
Identifier of the user who created the service. The user must exist. If it is not passed, the method writes the identifier of the current user |
|
modifiedBy |
Identifier of the user who last modified the service. The user must exist. If it is not passed, the method writes the identifier of the current user |
|
dateActiveFrom |
Activity start date. Currently the date cannot be set: a string in any format causes the "Incorrect starting date format" error, and a number is ignored. |
|
dateActiveTo |
Activity end date. Currently the date cannot be set: a string in any format causes the "Incorrect expiration date format" error, and a number is ignored. |
|
iblockSectionId |
Identifier of the main catalog section. You can retrieve the identifier using the catalog.section.list method. For a nonexistent section, the method returns the |
|
measure |
Identifier of the unit of measurement. You can retrieve the identifier using the catalog.measure.list method. If it is not passed, |
|
previewText |
Preview description |
|
previewTextType |
Type of the preview description. Possible values:
Default is |
|
detailText |
Detailed description |
|
detailTextType |
Type of the detailed description. Possible values:
Default is |
|
previewPicture |
Preview picture. An object in the |
|
detailPicture |
Detailed picture. An object in the |
|
vatId |
Identifier of the VAT rate. The rate must exist. You can retrieve the identifier using the catalog.vat.list method |
|
vatIncluded |
Whether VAT is included in the price. Possible values:
Default is |
|
propertyN |
Value of the service property, where You can pass the value as a string, a number, or an object You can retrieve property identifiers using the catalog.product.service.getFieldsByFilter method |
The method fills in the id, type, available, bundle, dateCreate, and timestampX fields itself: type is always 7 for a service, and the dates are the creation time. The method skips passed values of these fields and unknown fields without an error. The exception is dateCreate: currently a passed date is saved incorrectly, for example 2026-11-01T10:00:00+01:00 is saved as 2001-11-30T00:00:00+01:00, so do not pass this field.
Service Price
To set the service price, use the catalog.price.* methods.
Code Examples
How to Use Examples in Documentation
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"fields":{"iblockId":25,"name":"Air conditioner installation","code":"ac_installation","xmlId":"srv-ac-01","sort":200,"vatId":9,"vatIncluded":"Y","measure":9,"previewText":"Installation of a split system up to 3.5 kW","detailText":"<p>Installation of the indoor and outdoor units</p>","detailTextType":"html","previewPicture":{"fileData":["ac.png","iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII="]},"property301":"SRV-AC-01","property303":"Klima Service GmbH"}}' \
https://**put_your_bitrix24_address**/rest/**put_your_user_id_here**/**put_your_webhook_here**/catalog.product.service.add
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"fields":{"iblockId":25,"name":"Air conditioner installation","code":"ac_installation","xmlId":"srv-ac-01","sort":200,"vatId":9,"vatIncluded":"Y","measure":9,"previewText":"Installation of a split system up to 3.5 kW","detailText":"<p>Installation of the indoor and outdoor units</p>","detailTextType":"html","previewPicture":{"fileData":["ac.png","iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII="]},"property301":"SRV-AC-01","property303":"Klima Service GmbH"},"auth":"**put_access_token_here**"}' \
https://**put_your_bitrix24_address**/rest/catalog.product.service.add
// 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, ISODate } from '@bitrix24/b24jssdk'
declare const $b24: B24Frame
type PictureInfo = { id: string; url: string; urlMachine: string }
type PropertyValue = { value: string; valueId: string }
// Shape of the payload returned in result (match the "response handling" section of the page)
type ServiceAddResult = {
service: {
id: number
iblockId: number
name: string
active: string
code: string | null
xmlId: string
sort: number
type: number
measure: number | null
vatId: number | null
vatIncluded: string
previewText: string | null
previewPicture: PictureInfo | null
detailPicture: PictureInfo | null
dateCreate: ISODate
timestampX: ISODate
// Properties come as propertyN: null, a string, an object or an array of objects
[key: `property${number}`]: PropertyValue | PropertyValue[] | string | null
}
}
try {
const response = await $b24.actions.v2.call.make<ServiceAddResult>({
method: 'catalog.product.service.add',
params: {
fields: {
iblockId: 25,
name: 'Air conditioner installation',
code: 'ac_installation',
xmlId: 'srv-ac-01',
sort: 200,
vatId: 9,
vatIncluded: 'Y',
measure: 9,
previewText: 'Installation of a split system up to 3.5 kW',
detailText: '<p>Installation of the indoor and outdoor units</p>',
detailTextType: 'html',
previewPicture: {
fileData: ['ac.png', 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII='],
},
property301: 'SRV-AC-01',
property303: 'Klima Service GmbH',
},
},
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('Added service:', result.service.id, result.service.name)
}
} catch (error) {
// Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
console.error(error)
}
<!-- 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 addService() {
try {
// Initialize the SDK inside a Bitrix24 frame
const $b24 = await B24Js.initializeB24Frame()
const response = await $b24.actions.v2.call.make({
method: 'catalog.product.service.add',
params: {
fields: {
iblockId: 25,
name: 'Air conditioner installation',
code: 'ac_installation',
xmlId: 'srv-ac-01',
sort: 200,
vatId: 9,
vatIncluded: 'Y',
measure: 9,
previewText: 'Installation of a split system up to 3.5 kW',
detailText: '<p>Installation of the indoor and outdoor units</p>',
detailTextType: 'html',
previewPicture: {
fileData: ['ac.png', 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII='],
},
property301: 'SRV-AC-01',
property303: 'Klima Service GmbH',
},
},
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('Added service:', result.service.id, result.service.name)
} catch (error) {
// Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
console.error(error)
}
}
document.addEventListener('DOMContentLoaded', addService)
</script>
from b24pysdk.errors import BitrixAPIError, BitrixSDKException
try:
bitrix_response = client.catalog.product.service.add(
fields={
"iblockId": 25,
"name": "Air conditioner installation",
"code": "ac_installation",
"xmlId": "srv-ac-01",
"sort": 200,
"vatId": 9,
"vatIncluded": "Y",
"measure": 9,
"previewText": "Installation of a split system up to 3.5 kW",
"detailText": "<p>Installation of the indoor and outdoor units</p>",
"detailTextType": "html",
"previewPicture": {
"fileData": ["ac.png", "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII="],
},
"property301": "SRV-AC-01",
"property303": "Klima Service GmbH",
},
).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}")
try {
$response = $b24Service
->core
->call(
'catalog.product.service.add',
[
'fields' => [
'iblockId' => 25,
'name' => 'Air conditioner installation',
'code' => 'ac_installation',
'xmlId' => 'srv-ac-01',
'sort' => 200,
'vatId' => 9,
'vatIncluded' => 'Y',
'measure' => 9,
'previewText' => 'Installation of a split system up to 3.5 kW',
'detailText' => '<p>Installation of the indoor and outdoor units</p>',
'detailTextType' => 'html',
'previewPicture' => [
'fileData' => ['ac.png', 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII='],
],
'property301' => 'SRV-AC-01',
'property303' => 'Klima Service GmbH',
],
]
);
$result = $response
->getResponseData()
->getResult();
print_r($result);
} catch (Throwable $e) {
echo $e->getMessage();
}
BX24.callMethod(
'catalog.product.service.add',
{
fields: {
iblockId: 25,
name: 'Air conditioner installation',
code: 'ac_installation',
xmlId: 'srv-ac-01',
sort: 200,
vatId: 9,
vatIncluded: 'Y',
measure: 9,
previewText: 'Installation of a split system up to 3.5 kW',
detailText: '<p>Installation of the indoor and outdoor units</p>',
detailTextType: 'html',
previewPicture: {
fileData: ['ac.png', 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII='],
},
property301: 'SRV-AC-01',
property303: 'Klima Service GmbH',
},
},
function(result)
{
if (result.error())
console.error(result.error());
else
console.log(result.data());
}
);
require_once('crest.php');
$result = CRest::call(
'catalog.product.service.add',
[
'fields' => [
'iblockId' => 25,
'name' => 'Air conditioner installation',
'code' => 'ac_installation',
'xmlId' => 'srv-ac-01',
'sort' => 200,
'vatId' => 9,
'vatIncluded' => 'Y',
'measure' => 9,
'previewText' => 'Installation of a split system up to 3.5 kW',
'detailText' => '<p>Installation of the indoor and outdoor units</p>',
'detailTextType' => 'html',
'previewPicture' => [
'fileData' => ['ac.png', 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII='],
],
'property301' => 'SRV-AC-01',
'property303' => 'Klima Service GmbH',
]
]
);
echo '<PRE>';
print_r($result);
echo '</PRE>';
// client and ctx are already created — see the Go SDK section
res, err := client.Core().Call(ctx, "catalog.product.service.add", b24.Params{
"fields": b24.Params{
"iblockId": 25,
"name": "Air conditioner installation",
"code": "ac_installation",
"xmlId": "srv-ac-01",
"sort": 200,
"vatId": 9,
"vatIncluded": "Y",
"measure": 9,
"previewText": "Installation of a split system up to 3.5 kW",
"detailText": "<p>Installation of the indoor and outdoor units</p>",
"detailTextType": "html",
"previewPicture": b24.Params{
"fileData": []string{"ac.png", "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR4nGPQqDiBFTEMLQkAAtVaAcSRe60AAAAASUVORK5CYII="},
},
"property301": "SRV-AC-01",
"property303": "Klima Service GmbH",
},
})
if err != nil {
return fmt.Errorf("catalog.product.service.add: %w", err)
}
// The method wraps the response in an object with the "service" key.
raw, ok := b24.Unwrap(res.Result, "service")
if !ok {
return fmt.Errorf("no service key in the response")
}
// Optional fields can be null, so pointers are used for them.
var item struct {
ID b24.ID `json:"id"`
IblockID int `json:"iblockId"`
Name string `json:"name"`
Code *string `json:"code"`
XMLID string `json:"xmlId"`
Sort int `json:"sort"`
Type int `json:"type"`
Measure *int `json:"measure"`
VatID *int `json:"vatId"`
VatIncluded string `json:"vatIncluded"`
PreviewPicture *struct {
ID string `json:"id"`
URL string `json:"url"`
} `json:"previewPicture"`
}
if err := json.Unmarshal(raw, &item); err != nil {
return fmt.Errorf("parse response: %w", err)
}
fmt.Println(item.ID, item.Name)
Response Handling
HTTP status: 200
{
"result": {
"service": {
"active": "Y",
"available": "N",
"bundle": "N",
"code": "ac_installation",
"createdBy": 1269,
"dateActiveFrom": null,
"dateActiveTo": null,
"dateCreate": "2026-11-05T18:19:49+01:00",
"detailPicture": null,
"detailText": "<p>Installation of the indoor and outdoor units</p>",
"detailTextType": "html",
"iblockId": 25,
"iblockSection": null,
"iblockSectionId": null,
"id": 7623,
"measure": 9,
"modifiedBy": 1269,
"name": "Air conditioner installation",
"previewPicture": {
"id": "40035",
"url": "/rest/catalog.product.download?fields%5BfieldName%5D=previewPicture&fields%5BfileId%5D=40035&fields%5BproductId%5D=7623",
"urlMachine": "/rest/catalog.product.download?fields%5BfieldName%5D=previewPicture&fields%5BfileId%5D=40035&fields%5BproductId%5D=7623"
},
"previewText": "Installation of a split system up to 3.5 kW",
"previewTextType": "text",
"property293": null,
"property295": "N",
"property297": "N",
"property299": "N",
"property301": {
"value": "SRV-AC-01",
"valueId": "4059"
},
"property303": {
"value": "Klima Service GmbH",
"valueId": "4061"
},
"property305": null,
"property307": null,
"property309": null,
"property311": null,
"property313": null,
"property315": null,
"property329": null,
"property343": null,
"property359": null,
"property431": null,
"property433": null,
"property435": null,
"property893": null,
"property897": null,
"property901": null,
"property917": null,
"property921": null,
"property931": null,
"property933": null,
"property935": null,
"property1013": null,
"property1015": null,
"property1019": null,
"property1021": null,
"property1023": null,
"property1077": null,
"property1081": null,
"property1083": null,
"property1085": null,
"sort": 200,
"timestampX": "2026-11-05T18:19:49+01:00",
"type": 7,
"vatId": 9,
"vatIncluded": "Y",
"xmlId": "srv-ac-01"
}
},
"time": {
"start": 1793891989,
"finish": 1793891989.83412,
"duration": 0.8341200351715088,
"processing": 0,
"date_start": "2026-11-05T18:19:49+01:00",
"date_finish": "2026-11-05T18:19:49+01:00",
"operating_reset_at": 1793892589,
"operating": 0
}
}
Returned Data
|
Name |
Description |
|
result |
Root element of the response |
|
result.service |
Object with the fields of the created service. The method returns all fields, including empty ones with the The value of a filled property is an object |
|
time |
Information about the request execution time |
Error Handling
HTTP status: 400
{
"error": "0",
"error_description": "Required fields: name"
}
|
Name |
Description |
|
error |
String error code. It consists of digits, Latin letters, and underscores. It may arrive empty — in that case only |
|
error_description |
Error message for the developer. Do not show it to the end user without processing |
Possible Error Codes
|
Status |
Code |
Description |
Value |
|
|
|
Access Denied |
The user has none of the "View product catalog", "View catalog products", or "Edit selling price" access permissions |
|
|
|
Access Denied |
The user does not have the "Create product" access permission |
|
|
|
Access Denied |
The user does not have the permission to edit elements of the catalog information block |
|
|
|
Access Denied |
The |
|
|
|
Could not find value for parameter |
The |
|
|
|
Incorrect fields format |
|
|
|
|
Required fields: name |
A required field is not provided. The text lists the missing fields |
|
|
|
iblock is not catalog |
|
|
|
|
productType is not allowed for this catalog |
|
|
|
|
VAT vatId is not exists |
The VAT rate with the specified |
|
|
|
User createdBy is not exists |
The |
|
|
|
User modifiedBy is not exists |
The |
|
|
|
Incorrect starting date format. |
|
|
|
|
Incorrect expiration date format. |
|
|
|
|
Wrong format value of field |
A single property contains an array. The text names the property |
|
|
|
Wrong format of field |
The field contains an array or an object instead of a value. The text names the field |
Statuses and System Error Codes
HTTP Status: 4xx, 5xx
The errors described below are returned by the REST API itself, not by the logic of a specific method. They can arrive in response to any method.
|
Status |
Code |
Description |
|
|
|
An internal server error has occurred. Retry the call, and if the error persists, contact the server administrator or Bitrix24 technical support |
|
|
|
The server returned an unexpected response. Retry the call, and if the error persists, contact the server administrator or Bitrix24 technical support |
|
|
|
The request intensity limit has been exceeded |
|
|
|
The method is blocked because the request resource intensity limit has been exceeded. The block is lifted automatically once the accumulated execution time of the method no longer exceeds the limit |
|
|
|
The request contains no authorization data: neither an access token nor a webhook code was passed |
|
|
|
Methods are called over the HTTPS protocol only |
|
|
|
The REST API is blocked due to overload. This is a manual individual block. To have it lifted, contact Bitrix24 technical support |
|
|
|
REST API access is not active for this account. In Bitrix24 Cloud, check the current plan or trial status: Vibe+ plans include REST API access, while Essentials plans do not. A webhook receives a different error message — |
|
|
|
No active webhook with the specified user identifier and secret code was found |
|
|
|
No method with this name was found. The name is misspelled, the method does not exist in the REST API, or it is unavailable without the required scope |
|
|
|
The request requires broader permissions than the token has: for a webhook these are the permissions granted to it, for an application it is the scope. For an application, the error message ends with |
|
|
|
The access token has expired |
|
|
|
The application is installed, but the Bitrix24 administrator has granted access to it only to specific users |
|
|
|
The public part of the site is closed. To open it on an on-premise installation, disable the "Temporary closure of the public part of the site" option. Path to the setting: Desktop > Settings > Product Settings > Module Settings > Main Module > Temporary closure of the public part of the site |
Continue Learning
- Update Service Fields catalog.product.service.update
- Get Service Field Values catalog.product.service.get
- Get List of Services catalog.product.service.list
- Delete Service catalog.product.service.delete
- Download Service Files catalog.product.service.download
- Get Service Fields by Filter catalog.product.service.getFieldsByFilter