
## Offer fields

`GET /v1/catalog-offers/fields`

Returns the offer 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.

With the `iblockId` parameter, the reference also includes the fields of a specific offer catalog — its `propertyNNN` properties.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|---------|
| `iblockId` (query) | number | no | Offer catalog ID from [`GET /v1/catalogs`](/docs/entities/catalogs); this catalog has `productIblockId` filled in. With it, the response contains the catalog properties `propertyNNN` and the service fields `negativeAmountTrace`, `priceType`. Without the parameter, with a product catalog ID, or with a nonexistent ID, the response carries the base set of 44 fields and the `fields_partial` warning in `meta.warnings` |

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/catalog-offers/fields?iblockId=27" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/catalog-offers/fields?iblockId=27" \
  -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-offers/fields?iblockId=27', {
  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-offers/fields?iblockId=27', {
  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); numeric functions accept the fields of type `number`. `data.batch` lists the operations available in a [batch request](/docs/batch).

| Field | Type | RO | Description |
|------|-----|:--:|---------|
| `id` | number | yes | Offer identifier |
| `name` | string | no | Offer name. Required on create |
| `active` | boolean | no | Whether the offer is active |
| `iblockId` | number | no¹ | Offer catalog ID. List: [`GET /v1/catalogs`](/docs/entities/catalogs). Required on create, set on create only |
| `parentId` | object \| null | no² | Link to the parent product: `value` — the parent product ID as a string, `valueId` — the service ID of the link value, read-only. On create, pass `{ "value": "<ID>" }`. `null` — a free offer. Parent product IDs: [`GET /v1/catalog-skus`](/docs/entities/catalog-skus/list) |
| `type` | number | yes | Record type, computed by Bitrix24: `4` — the offer is linked to a parent product, `5` — a free offer. The filter accepts one exact value |
| `iblockSectionId` | number \| null | no | Catalog section ID. `null` — the offer is not linked to a section. List: [`GET /v1/catalog-sections`](/docs/entities/catalog-sections) |
| `purchasingPrice` | number \| null | no | Purchase price. `null` if not set |
| `purchasingCurrency` | string \| null | no | Purchase price currency, for example `USD`. `null` if the purchase price is not set. List: [`GET /v1/currencies`](/docs/entities/currencies) |
| `quantity` | number \| null | no | Stock balance. `null` if not set |
| `weight` | number \| null | no | Weight of a product unit. `null` if not specified |
| `measure` | number | no | Unit of measure ID. List: [`GET /v1/catalog-measures`](/docs/entities/catalog-measures) |
| `available` | boolean | yes | Whether the offer is available for purchase. Computed by Bitrix24 |
| `vatIncluded` | boolean | no | VAT included in the price |
| `bundle` | boolean | yes | Whether the offer is a bundle. Computed by Bitrix24 |
| `canBuyZero` | boolean | no | Allow purchase when stock is zero |
| `quantityTrace` | boolean | no | Quantity tracking enabled |
| `subscribe` | boolean | no | Allow subscription to the product |
| `barcodeMulti` | boolean | no | Allow separate barcodes for product units |
| `withoutOrder` | boolean | no | Available for ordering without stock on hand |
| `dateActiveFrom` | datetime | no | Activity start date |
| `dateActiveTo` | datetime | no | Activity end date |
| `createdBy` | number | yes | ID of the user who created the offer. List: [`GET /v1/users`](/docs/entities/users) |
| `modifiedBy` | number | yes | ID of the user who last modified the offer. List: [`GET /v1/users`](/docs/entities/users) |
| `dateCreate` | datetime | yes | Creation date |
| `timestampX` | datetime | yes | Last modification date |
| `code` | string \| null | no | Symbolic code. `null` if not set |
| `xmlId` | string | no | External identifier |
| `sort` | number | no | Sort order |
| `vatId` | number | no | VAT rate ID. List: [`GET /v1/catalog-vat-rates`](/docs/entities/catalog-vat-rates) |
| `previewText` | string | no | Preview text |
| `detailText` | string | no | Detailed description |
| `previewTextType` | string | no | Preview text format: `text` or `html` |
| `detailTextType` | string | no | Detailed description format: `text` or `html` |
| `previewPicture` | object | no | Preview image |
| `detailPicture` | object | no | Detail image |
| `iblockSection` | object | no | Array of catalog section IDs to write on create and update. The primary section is read from `iblockSectionId`. List: [`GET /v1/catalog-sections`](/docs/entities/catalog-sections) |
| `width` | number | no | Width |
| `height` | number | no | Height |
| `length` | number | no | Length |
| `quantityReserved` | number \| null | no | Reserved quantity. `null` if nothing is reserved |
| `recurSchemeLength` | number | no | Payment period length. Available only in on-premise Bitrix24 for content sales |
| `recurSchemeType` | string | no | Payment period time unit: `H` — hour, `D` — day, `W` — week, `M` — month, `Q` — quarter, `S` — half-year, `Y` — year. Available only in on-premise Bitrix24 for content sales |
| `trialPriceId` | number | no | ID of the product used for a trial payment. Available only in on-premise Bitrix24 for content sales |
| `negativeAmountTrace` | char | yes | Catalog service field. Returned only with `iblockId` |
| `priceType` | char | no | Catalog service field. Returned only with `iblockId` |
| `propertyNNN` | productproperty | no | Catalog property, where `NNN` is the property `id` from [`GET /v1/catalog-product-properties`](/docs/entities/catalog-product-properties). Returned only with `iblockId`; multiple-value properties come with `multiple: true` |

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

² `parentId` is writable on create only — in the reference it comes back with `readonly: false` and `readonlyOnUpdate: true`.

Request headers do not switch the language of labels and descriptions. A field with a fixed set of values — `previewTextType` and `detailTextType` — also carries an `enum` array: every element holds a `value` to pass in the request and a `label` for display.

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data.fields.<name>.type` | string | Field type: `number`, `string`, `boolean`, `datetime`, `object`. Catalog fields use `char` and `productproperty` |
| `data.fields.<name>.label` | string | Short field label. For catalog fields the label matches the field name |
| `data.fields.<name>.description` | string | Extended field description: what it is for, where to get the list of allowed values, write-time behavior. The key is present on fields that have something to add to the label |
| `data.fields.<name>.readonly` | boolean | `true` — the field is filled by the system and is not accepted on create or update |
| `data.fields.<name>.required` | boolean | `true` — the field is required on create. Present on `name` and `iblockId` |
| `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>.readonlyOnUpdate` | boolean | `true` — the field is accepted on create; on `PATCH` it is rejected with `READONLY_FIELD`. Present on `parentId` |
| `data.fields.<name>.properties` | object | Nested keys of an object field with their types. On `parentId` — `value` and `valueId`, the latter with `readonly: true` |
| `data.fields.<name>.writeOnly` | boolean | `true` — the field is accepted on write and is not returned in responses. Present on `iblockSection` |
| `data.fields.<name>.notReturned` | boolean | `true` — the field name is not supported in `select`: a list request with it returns an `UNKNOWN_SELECT_FIELD` warning. 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.fields.<name>.multiple` | boolean | `true` — the catalog property accepts several values. The key is present only on such properties |
| `data.aggregatable` | string[] | Fields for `groupBy` in [aggregation](./aggregate.md): `purchasingPrice`, `quantity`, `iblockSectionId` |
| `data.batch` | string[] | Offer operations available in a [batch request](/docs/batch): `create`, `update`, `delete` |
| `meta.warnings` | array | Warnings. An element with `code: fields_partial` arrives when the response is built without catalog fields — without `iblockId`, or with an `iblockId` that does not belong to an offer catalog |

## Response example

```json
{
  "success": true,
  "data": {
    "fields": {
      "id": {
        "type": "number",
        "readonly": true,
        "label": "Product identifier",
        "description": "Unique identifier of the catalog product."
      },
      "iblockId": {
        "type": "number",
        "readonly": false,
        "createOnly": true,
        "required": true,
        "label": "Catalog ID",
        "description": "Catalog the product belongs to. Available values: GET /v1/catalogs. Set on create only — changing it via PATCH is rejected, a product cannot be moved between catalogs."
      },
      "parentId": {
        "type": "object",
        "readonly": false,
        "readonlyOnUpdate": true,
        "nullable": true,
        "label": "Parent product ID",
        "description": "Link to a catalog SKU or product. On create pass {\"value\":\"<parent id>\"}; omit for a free offer. Bitrix24 returns value and valueId. Updates to this field are rejected because Bitrix24 silently ignores them.",
        "properties": {
          "value": { "type": "string" },
          "valueId": { "type": "string", "readonly": true }
        }
      },
      "type": {
        "type": "number",
        "readonly": true,
        "label": "Bitrix24 product type",
        "description": "Computed by Bitrix24. A free offer has a different type from an offer linked to a parent. Filtering accepts only exact type 4 or 5."
      },
      "iblockSection": {
        "type": "object",
        "readonly": false,
        "writeOnly": true,
        "notReturned": true,
        "label": "Catalog sections",
        "description": "Array of catalog section IDs the product 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" }
        ]
      },
      "property909": {
        "type": "productproperty",
        "readonly": false,
        "multiple": true,
        "label": "property909"
      }
    },
    "aggregatable": [
      "purchasingPrice",
      "quantity",
      "iblockSectionId"
    ],
    "batch": [
      "create",
      "update",
      "delete"
    ]
  }
}
```

The example is trimmed to seven fields — one each for `readonly`, `createOnly` with `required`, `readonlyOnUpdate` with `properties`, the computed `type`, the `writeOnly` + `notReturned` pair, an `enum` dictionary and a multiple-value catalog property. With `iblockId=27`, the test Bitrix24 account returns 55 fields.

Without `iblockId`, the response contains a warning:

```json
{
  "success": true,
  "data": { "fields": { /* 44 fields */ }, "aggregatable": [ /* ... */ ], "batch": [ /* ... */ ] },
  "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."
      }
    ]
  }
}
```

## 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

**A retry does not clear `fields_partial` without `iblockId`.** The warning suggests retrying the request, but without the offer catalog's `iblockId` a retry returns the same base set. The forty-four base fields in this response are complete; only the catalog properties and service fields are missing — a request with `?iblockId=` returns them.

**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 dimensions `width`, `height`, `length`, the texts, the pictures, `quantityReserved`, `recurSchemeLength`, `recurSchemeType`, `trialPriceId` and the `propertyNNN` properties are not returned in the [`GET /v1/catalog-offers`](./list.md) response without an explicit `?select=`. List the names you need in `select` to get them in the list. The single-offer response, [`GET /v1/catalog-offers/:id`](./get.md), always returns them.

**Labels call the record a product.** In the reference's `label` and `description`, an offer is called a product — the labels match [Catalog product fields](/docs/entities/catalog-products/fields). The `type` and `parentId` fields exist only on offers.

## See also

- [List offers](/docs/entities/catalog-offers/list)
- [Create an offer](/docs/entities/catalog-offers/create)
- [Search offers](/docs/entities/catalog-offers/search)
- [Catalog SKUs](/docs/entities/catalog-skus)
- [Catalog product properties](/docs/entities/catalog-product-properties)
- [API reference](/docs/api-reference)
