# Каталог и склад

Управляйте каталогом товаров, ценами и складскими остатками через Entity API. Разделы каталога, ценовые предложения, склады — всё через стандартные CRUD-операции.

## Обзор

Catalog API расширяет базовые entity-обёртки для торгового каталога Битрикс24:

- **Разделы каталога** (`/v1/catalog-sections/*`) — категории и подкатегории товаров
- **Цены** (`/v1/catalog-prices/*`) — ценовые предложения (прайс-листы)
- **Склады** (`/v1/warehouses/*`) — управление складами и остатками

**Требуемые скоупы:** `catalog`, `crm`

**Базовый URL:** `https://vibecode.bitrix24.tech/v1`

**Авторизация:** заголовок `X-Api-Key` с вашим API-ключом.

## Быстрый старт

### Создайте раздел каталога

```bash
curl -X POST https://vibecode.bitrix24.tech/v1/catalog-sections \
  -H "X-Api-Key: $VIBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "iblockId": 14,
      "name": "Электроника",
      "iblockSectionId": null
    }
  }'
```

Ответ:

```json
{
  "success": true,
  "data": {
    "section": {
      "id": 42
    }
  }
}
```

## Разделы каталога

Entity: `catalog-sections` — разделы (категории) торгового каталога.

### POST /v1/catalog-sections

Создаёт новый раздел каталога.

**Параметры тела запроса (в `fields`):**

| Параметр | Тип | Обязательный | Описание |
|----------|-----|:---:|---------|
| `iblockId` | number | да | ID инфоблока каталога |
| `name` | string | да | Название раздела |
| `iblockSectionId` | number | нет | ID родительского раздела (`null` — корневой) |
| `xmlId` | string | нет | Внешний ID для синхронизации |
| `description` | string | нет | Описание раздела |
| `sort` | number | нет | Порядок сортировки |

**JavaScript:**

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/catalog-sections', {
  method: 'POST',
  headers: {
    'X-Api-Key': VIBE_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fields: {
      iblockId: 14,
      name: 'Смартфоны',
      iblockSectionId: 42,  // дочерний раздел "Электроники"
      sort: 100
    }
  })
})

const { data } = await res.json()
console.log('Section ID:', data.section.id)
```

### GET /v1/catalog-sections

Возвращает список разделов каталога с фильтрацией.

```bash
curl -H "X-Api-Key: $VIBE_KEY" \
  "https://vibecode.bitrix24.tech/v1/catalog-sections?filter[iblockId]=14"
```

### GET /v1/catalog-sections/:id

Получает раздел по ID.

```bash
curl -H "X-Api-Key: $VIBE_KEY" \
  https://vibecode.bitrix24.tech/v1/catalog-sections/42
```

### PATCH /v1/catalog-sections/:id

Обновляет раздел каталога.

```bash
curl -X PATCH https://vibecode.bitrix24.tech/v1/catalog-sections/42 \
  -H "X-Api-Key: $VIBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "name": "Электроника и гаджеты",
      "sort": 50
    }
  }'
```

### DELETE /v1/catalog-sections/:id

Удаляет раздел каталога.

```bash
curl -X DELETE -H "X-Api-Key: $VIBE_KEY" \
  https://vibecode.bitrix24.tech/v1/catalog-sections/42
```

## Цены

Entity: `catalog-prices` — ценовые предложения для товаров.

### POST /v1/catalog-prices

Создаёт новое ценовое предложение для товара.

**Параметры тела запроса (в `fields`):**

| Параметр | Тип | Обязательный | Описание |
|----------|-----|:---:|---------|
| `catalogGroupId` | number | да | ID типа цены |
| `productId` | number | да | ID товара |
| `price` | number | да | Цена |
| `currency` | string | да | Валюта (`RUB`, `USD`, `EUR`) |
| `quantityFrom` | number | нет | Количество «от» для оптовой цены |
| `quantityTo` | number | нет | Количество «до» |

```bash
curl -X POST https://vibecode.bitrix24.tech/v1/catalog-prices \
  -H "X-Api-Key: $VIBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "catalogGroupId": 1,
      "productId": 200,
      "price": 49990,
      "currency": "RUB"
    }
  }'
```

**JavaScript — оптовые цены:**

```javascript
// Розничная цена
await fetch('https://vibecode.bitrix24.tech/v1/catalog-prices', {
  method: 'POST',
  headers: {
    'X-Api-Key': VIBE_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fields: {
      catalogGroupId: 1,  // розничная
      productId: 200,
      price: 49990,
      currency: 'RUB'
    }
  })
})

// Оптовая цена (от 10 штук)
await fetch('https://vibecode.bitrix24.tech/v1/catalog-prices', {
  method: 'POST',
  headers: {
    'X-Api-Key': VIBE_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fields: {
      catalogGroupId: 2,  // оптовая
      productId: 200,
      price: 39990,
      currency: 'RUB',
      quantityFrom: 10
    }
  })
})
```

### GET /v1/catalog-prices

Список цен с фильтрацией по товару.

```bash
curl -H "X-Api-Key: $VIBE_KEY" \
  "https://vibecode.bitrix24.tech/v1/catalog-prices?filter[productId]=200"
```

### GET /v1/catalog-prices/:id

Получает цену по ID.

```bash
curl -H "X-Api-Key: $VIBE_KEY" \
  https://vibecode.bitrix24.tech/v1/catalog-prices/15
```

### PATCH /v1/catalog-prices/:id

Обновляет цену.

```bash
curl -X PATCH https://vibecode.bitrix24.tech/v1/catalog-prices/15 \
  -H "X-Api-Key: $VIBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": { "price": 44990 }
  }'
```

### DELETE /v1/catalog-prices/:id

Удаляет ценовое предложение.

```bash
curl -X DELETE -H "X-Api-Key: $VIBE_KEY" \
  https://vibecode.bitrix24.tech/v1/catalog-prices/15
```

## Склады

Склады и складские остатки вынесены в отдельный раздел — **[Склады](/docs/entities/warehouses)** — с отдельной страницей на каждую операцию и проверенными примерами.

## Полный пример: Синхронизация каталога из 1С

```javascript
const VIBE_KEY = process.env.VIBE_KEY
const BASE = 'https://vibecode.bitrix24.tech/v1'

async function api(method, path, body = null) {
  const opts = {
    method,
    headers: { 'X-Api-Key': VIBE_KEY }
  }
  if (body) {
    opts.headers['Content-Type'] = 'application/json'
    opts.body = JSON.stringify(body)
  }
  const res = await fetch(`${BASE}${path}`, opts)
  return res.json()
}

// Данные из 1С
const categories = [
  { name: 'Электроника', xmlId: '1c_cat_001', children: [
    { name: 'Смартфоны', xmlId: '1c_cat_002' },
    { name: 'Ноутбуки', xmlId: '1c_cat_003' }
  ]},
  { name: 'Аксессуары', xmlId: '1c_cat_010' }
]

const IBLOCK_ID = 14

// 1. Создаём корневые разделы
for (const cat of categories) {
  const { data } = await api('POST', '/catalog-sections', {
    fields: {
      iblockId: IBLOCK_ID,
      name: cat.name,
      xmlId: cat.xmlId
    }
  })
  const parentId = data.section.id
  console.log(`Раздел "${cat.name}" создан, ID: ${parentId}`)

  // 2. Создаём дочерние разделы
  if (cat.children) {
    for (const child of cat.children) {
      const { data: childData } = await api('POST', '/catalog-sections', {
        fields: {
          iblockId: IBLOCK_ID,
          name: child.name,
          xmlId: child.xmlId,
          iblockSectionId: parentId
        }
      })
      console.log(`  Подраздел "${child.name}" создан, ID: ${childData.section.id}`)
    }
  }
}

// 3. Устанавливаем цены на товары
const products = [
  { id: 200, retail: 49990, wholesale: 39990 },
  { id: 201, retail: 79990, wholesale: 64990 }
]

for (const product of products) {
  // Розничная цена
  await api('POST', '/catalog-prices', {
    fields: {
      catalogGroupId: 1,
      productId: product.id,
      price: product.retail,
      currency: 'RUB'
    }
  })

  // Оптовая цена
  await api('POST', '/catalog-prices', {
    fields: {
      catalogGroupId: 2,
      productId: product.id,
      price: product.wholesale,
      currency: 'RUB',
      quantityFrom: 10
    }
  })

  console.log(`Цены для товара ${product.id}: розн. ${product.retail}, опт. ${product.wholesale}`)
}

console.log('Синхронизация завершена')
```

## Справочник эндпоинтов

| Метод | Путь | Bitrix24 метод | Описание |
|-------|------|---------------|---------|
| POST | /v1/catalog-sections | catalog.section.add | Создать раздел |
| GET | /v1/catalog-sections | catalog.section.list | Список разделов |
| GET | /v1/catalog-sections/:id | catalog.section.get | Получить раздел |
| PATCH | /v1/catalog-sections/:id | catalog.section.update | Обновить раздел |
| DELETE | /v1/catalog-sections/:id | catalog.section.delete | Удалить раздел |
| POST | /v1/catalog-prices | catalog.price.add | Создать цену |
| GET | /v1/catalog-prices | catalog.price.list | Список цен |
| GET | /v1/catalog-prices/:id | catalog.price.get | Получить цену |
| PATCH | /v1/catalog-prices/:id | catalog.price.update | Обновить цену |
| DELETE | /v1/catalog-prices/:id | catalog.price.delete | Удалить цену |

## Коды ошибок

| Код | HTTP | Описание |
|-----|------|---------|
| `SCOPE_DENIED` | 403 | API-ключ не имеет скоупа `catalog` |
| `TOKEN_MISSING` | 401 | Ключ не имеет настроенных токенов |
| `SECTION_NOT_FOUND` | 404 | Раздел каталога не найден |
| `PRODUCT_NOT_FOUND` | 404 | Товар не найден |
| `BITRIX_UNAVAILABLE` | 502 | Битрикс24 недоступен |
| `BITRIX_ERROR` | 422 | Ошибка Bitrix24 REST API |
