## Service fields

`GET /v1/catalog-services/fields`

Returns the catalog service field reference with labels, types, write flags and dictionaries of allowed values, plus the fields available for aggregation and the operations available in a batch request.

The reference contains 28 service fields. Catalog properties of the form `propertyNNN` are not included: their values arrive in the [`GET /v1/catalog-services/:id`](./get.md) response, and their names and types in [`GET /v1/catalog-product-properties`](/docs/entities/catalog-product-properties/list).

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/catalog-services/fields" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/catalog-services/fields" \
  -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/catalog-services/fields', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data } = await res.json()
console.log('Fields:', Object.keys(data.fields).length)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/catalog-services/fields', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

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

## Response fields

`data.fields` is an object keyed by field name; each value contains the type, the write flags, a display label and — for fields with a fixed set of values — their dictionary. The set of keys is broken down in the table after the field list. `data.aggregatable` lists the fields for `groupBy` in [aggregation](./aggregate.md). `data.batch` lists the operations available in a [batch request](/docs/batch).

| Field | Type | RO | Description |
|------|-----|:--:|---------|
| `id` | number | yes | Service ID |
| `name` | string | no | Service name. Required on create |
| `active` | boolean | no | Whether the service is active |
| `available` | boolean | no | Whether the service is available for purchase. Without an explicit value, the service is created with `false` |
| `iblockId` | number | no¹ | Product catalog ID. List: [`GET /v1/catalogs`](/docs/entities/catalogs/list). Required on create, set on create only |
| `type` | number | yes | Record type, always `7` for a service. Set by Bitrix24 |
| `iblockSectionId` | number \| null | no | Primary catalog section ID. `null` — the service is not linked to a section. List: [`GET /v1/catalog-sections`](/docs/entities/catalog-sections/list) |
| `iblockSection` | object | no | Array of IDs of all catalog sections the service belongs to. Returned in the single-service response, not supported in the list `select`. List: [`GET /v1/catalog-sections`](/docs/entities/catalog-sections/list) |
| `measure` | number | no | Unit of measure ID. List: [`GET /v1/catalog-measures`](/docs/entities/catalog-measures/list) |
| `vatIncluded` | boolean | no | VAT is included in the price |
| `vatId` | number | no | VAT rate ID. List: [`GET /v1/catalog-vat-rates`](/docs/entities/catalog-vat-rates/list) |
| `bundle` | boolean | yes | Whether the service is a bundle. Computed by Bitrix24 |
| `code` | string \| null | no | Symbolic code. `null` if not set |
| `xmlId` | string | no | External identifier. If not set, equals the service `id` as a string |
| `sort` | number | no | Sort order. Defaults to `500` |
| `dateActiveFrom` | datetime | no | Activity start date |
| `dateActiveTo` | datetime | no | Activity end date |
| `createdBy` | number | yes | ID of the user who created the service. List: [`GET /v1/users`](/docs/entities/users/list) |
| `modifiedBy` | number | yes | ID of the user who last modified the service. List: [`GET /v1/users`](/docs/entities/users/list) |
| `dateCreate` | datetime | yes | Creation date |
| `timestampX` | datetime | yes | Last modification date |
| `previewText` | string | no | Preview text |
| `previewTextType` | string | no | Preview text format: `text` or `html` |
| `detailText` | string | no | Detailed description |
| `detailTextType` | string | no | Detailed description format: `text` or `html` |
| `previewPicture` | object | no | Preview image |
| `detailPicture` | object | no | Detail image |
| `priceType` | string | no | Declared in the reference, but not returned in the list or single-service responses. Service prices are set via [`POST /v1/catalog-prices`](/docs/entities/catalog-prices/create) |

¹ `iblockId` is writable on create only — in the reference it comes back with `readonly: false` and `createOnly: true`.

Field labels `label` and descriptions `description` arrive in English. Fields with a fixed set of values — `previewTextType` and `detailTextType` — also carry an `enum` dictionary: an array of `{ value, label }`. Send `value`; `label` is meant for display.

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data.fields.<name>.type` | string | Field type: `number`, `string`, `boolean`, `datetime`, `object` |
| `data.fields.<name>.label` | string | Short field label |
| `data.fields.<name>.description` | string | Extended field description: its purpose, where to get the list of allowed values, write-time behavior |
| `data.fields.<name>.readonly` | boolean | `true` — the field is filled by the system and is not accepted on create or update |
| `data.fields.<name>.createOnly` | boolean | `true` — the field is accepted on create only; on `PATCH` it is rejected with `READONLY_FIELD`. Present on `iblockId` |
| `data.fields.<name>.writeOnly` | boolean | `true` — the field is accepted on write. Present on `iblockSection` |
| `data.fields.<name>.notReturned` | boolean | `true` — the field name is not supported in `select`: list and search reject it with `SELECT_FIELD_NOT_RETURNED`. Present on `iblockSection` |
| `data.fields.<name>.nullable` | boolean | `true` — the field can come back as `null`. The key is present only on such fields |
| `data.aggregatable` | string[] | Fields for `groupBy` in [aggregation](./aggregate.md): `iblockSectionId` |
| `data.batch` | string[] | Service operations available in a [batch request](/docs/batch): `create`, `update`, `delete` |
| `meta.warnings` | array | Warnings. An element with `code: fields_partial` arrives in every response of this method |

## Response example

```json
{
  "success": true,
  "data": {
    "fields": {
      "id": {
        "type": "number",
        "readonly": true,
        "label": "Service identifier",
        "description": "Unique identifier of the catalog service."
      },
      "iblockId": {
        "type": "number",
        "readonly": false,
        "createOnly": true,
        "label": "Catalog ID",
        "description": "Catalog the service belongs to. Available values: GET /v1/catalogs. Set on create only — changing it via PATCH is rejected, a service cannot be moved between catalogs."
      },
      "type": {
        "type": "number",
        "readonly": true,
        "label": "Service type",
        "description": "Bitrix24 service type (7); set by Bitrix24 and read only."
      },
      "iblockSectionId": {
        "type": "number",
        "readonly": false,
        "nullable": true,
        "label": "Catalog section ID",
        "description": "Primary catalog section of the service; null when it is not linked to a section. Available values: GET /v1/catalog-sections."
      },
      "iblockSection": {
        "type": "object",
        "readonly": false,
        "writeOnly": true,
        "notReturned": true,
        "label": "Catalog sections",
        "description": "Array of catalog section IDs the service belongs to. Accepted on create and update only — on read the primary section arrives as the scalar iblockSectionId. Available values: GET /v1/catalog-sections."
      },
      "previewTextType": {
        "type": "string",
        "readonly": false,
        "label": "Preview text format",
        "description": "Format of previewText.",
        "enum": [
          { "value": "text", "label": "Plain text" },
          { "value": "html", "label": "HTML" }
        ]
      }
    },
    "aggregatable": [
      "iblockSectionId"
    ],
    "batch": [
      "create",
      "update",
      "delete"
    ]
  },
  "meta": {
    "warnings": [
      {
        "code": "fields_partial",
        "message": "Dynamic field metadata from Bitrix24 was unavailable; the response carries static schema fields only and some labels may be missing. Retry to obtain the complete set."
      }
    ]
  }
}
```

The example is trimmed to six fields — one each for the `readonly` and `createOnly` flags, the computed `type`, `nullable`, the `writeOnly` + `notReturned` pair and the `enum` dictionary. The full response contains 28 fields.

## Error response example

401 — the key was not passed:

```json
{
  "success": false,
  "error": {
    "code": "MISSING_API_KEY",
    "message": "API key required. Pass via X-Api-Key header."
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 403 | `SCOPE_DENIED` | The API key does not have the `catalog` scope |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not passed |
| 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 |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

**`fields_partial` always arrives and a retry does not clear it.** The warning advises repeating the request, but a retry returns the same response, and the `?iblockId=` parameter does not change it. The 28 fields of the reference are complete — only the catalog properties `propertyNNN` are missing.

**Some fields are not returned in the list by default.** The symbolic code `code`, the external code `xmlId`, the sort order `sort`, the VAT rate `vatId`, the texts, the images and the `propertyNNN` properties are not returned in the [`GET /v1/catalog-services`](./list.md) response without an explicit `?select=`. List the names you need in `select` to get them in the list. The single-service response, [`GET /v1/catalog-services/:id`](./get.md), always returns them.

## See also

- [List services](/docs/entities/catalog-services/list)
- [Create a service](/docs/entities/catalog-services/create)
- [Get a service](/docs/entities/catalog-services/get)
- [Catalog product properties](/docs/entities/catalog-product-properties)
- [Catalog products](/docs/entities/catalog-products)
- [API reference](/docs/api-reference)
