# Catalog and warehouse

Manage the product catalog, prices and stock levels through the Entity API. Catalog sections, price offers, warehouses — all via standard CRUD operations.

## Overview

The Catalog API extends the base entity wrappers for the Bitrix24 commerce catalog:

- **Catalog sections** (`/v1/catalog-sections/*`) — product categories and subcategories
- **Prices** (`/v1/catalog-prices/*`) — price offers (price lists)
- **Warehouses** (`/v1/warehouses/*`) — warehouse and stock management

**Required scopes:** `catalog`, `crm`

**Base URL:** `https://vibecode.bitrix24.com/v1`

**Authorization:** the `X-Api-Key` header with your API key.

## Quick start

### Create a catalog section

```bash
curl -X POST https://vibecode.bitrix24.com/v1/catalog-sections \
  -H "X-Api-Key: $VIBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "iblockId": 14,
      "name": "Electronics",
      "iblockSectionId": null
    }
  }'
```

Response:

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

## Catalog sections

Entity: `catalog-sections` — sections (categories) of the commerce catalog.

### POST /v1/catalog-sections

Creates a new catalog section.

**Request body parameters (in `fields`):**

| Parameter | Type | Required | Description |
|----------|-----|:---:|---------|
| `iblockId` | number | yes | Catalog information block ID |
| `name` | string | yes | Section name |
| `iblockSectionId` | number | no | Parent section ID (`null` — root) |
| `xmlId` | string | no | External ID for synchronization |
| `description` | string | no | Section description |
| `sort` | number | no | Sort order |

**JavaScript:**

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/catalog-sections', {
  method: 'POST',
  headers: {
    'X-Api-Key': VIBE_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fields: {
      iblockId: 14,
      name: 'Smartphones',
      iblockSectionId: 42,  // child section of "Electronics"
      sort: 100
    }
  })
})

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

### GET /v1/catalog-sections

Returns a list of catalog sections with filtering.

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

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

Gets a section by ID.

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

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

Updates a catalog section.

```bash
curl -X PATCH https://vibecode.bitrix24.com/v1/catalog-sections/42 \
  -H "X-Api-Key: $VIBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "name": "Electronics and gadgets",
      "sort": 50
    }
  }'
```

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

Deletes a catalog section.

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

## Prices

Entity: `catalog-prices` — price offers for products.

### POST /v1/catalog-prices

Creates a new price offer for a product.

**Request body parameters (in `fields`):**

| Parameter | Type | Required | Description |
|----------|-----|:---:|---------|
| `catalogGroupId` | number | yes | Price type ID |
| `productId` | number | yes | Product ID |
| `price` | number | yes | Price |
| `currency` | string | yes | Currency (`USD`, `EUR`, …) |
| `quantityFrom` | number | no | Quantity "from" for wholesale price |
| `quantityTo` | number | no | Quantity "to" |

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

**JavaScript — wholesale prices:**

```javascript
// Retail price
await fetch('https://vibecode.bitrix24.com/v1/catalog-prices', {
  method: 'POST',
  headers: {
    'X-Api-Key': VIBE_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fields: {
      catalogGroupId: 1,  // retail
      productId: 200,
      price: 49990,
      currency: 'USD'
    }
  })
})

// Wholesale price (from 10 units)
await fetch('https://vibecode.bitrix24.com/v1/catalog-prices', {
  method: 'POST',
  headers: {
    'X-Api-Key': VIBE_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fields: {
      catalogGroupId: 2,  // wholesale
      productId: 200,
      price: 39990,
      currency: 'USD',
      quantityFrom: 10
    }
  })
})
```

### GET /v1/catalog-prices

List of prices filtered by product.

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

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

Gets a price by ID.

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

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

Updates a price.

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

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

Deletes a price offer.

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

## Warehouses

Warehouses and stock levels are moved into a separate section — **[Warehouses](/docs/entities/warehouses)** — with a dedicated page for each operation and verified examples.

## Full example: Catalog synchronization from ERP

```javascript
const VIBE_KEY = process.env.VIBE_KEY
const BASE = 'https://vibecode.bitrix24.com/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()
}

// Data from ERP
const categories = [
  { name: 'Electronics', xmlId: 'erp_cat_001', children: [
    { name: 'Smartphones', xmlId: 'erp_cat_002' },
    { name: 'Laptops', xmlId: 'erp_cat_003' }
  ]},
  { name: 'Accessories', xmlId: 'erp_cat_010' }
]

const IBLOCK_ID = 14

// 1. Create root sections
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(`Section "${cat.name}" created, ID: ${parentId}`)

  // 2. Create child sections
  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(`  Subsection "${child.name}" created, ID: ${childData.section.id}`)
    }
  }
}

// 3. Set product prices
const products = [
  { id: 200, retail: 49990, wholesale: 39990 },
  { id: 201, retail: 79990, wholesale: 64990 }
]

for (const product of products) {
  // Retail price
  await api('POST', '/catalog-prices', {
    fields: {
      catalogGroupId: 1,
      productId: product.id,
      price: product.retail,
      currency: 'USD'
    }
  })

  // Wholesale price
  await api('POST', '/catalog-prices', {
    fields: {
      catalogGroupId: 2,
      productId: product.id,
      price: product.wholesale,
      currency: 'USD',
      quantityFrom: 10
    }
  })

  console.log(`Prices for product ${product.id}: retail ${product.retail}, wholesale ${product.wholesale}`)
}

console.log('Synchronization complete')
```

## Endpoint reference

| Method | Path | Bitrix24 method | Description |
|-------|------|---------------|---------|
| POST | /v1/catalog-sections | catalog.section.add | Create section |
| GET | /v1/catalog-sections | catalog.section.list | List sections |
| GET | /v1/catalog-sections/:id | catalog.section.get | Get section |
| PATCH | /v1/catalog-sections/:id | catalog.section.update | Update section |
| DELETE | /v1/catalog-sections/:id | catalog.section.delete | Delete section |
| POST | /v1/catalog-prices | catalog.price.add | Create price |
| GET | /v1/catalog-prices | catalog.price.list | List prices |
| GET | /v1/catalog-prices/:id | catalog.price.get | Get price |
| PATCH | /v1/catalog-prices/:id | catalog.price.update | Update price |
| DELETE | /v1/catalog-prices/:id | catalog.price.delete | Delete price |

## Error codes

| Code | HTTP | Description |
|-----|------|---------|
| `SCOPE_DENIED` | 403 | API key does not have the `catalog` scope |
| `TOKEN_MISSING` | 401 | Key has no configured tokens |
| `SECTION_NOT_FOUND` | 404 | Catalog section not found |
| `PRODUCT_NOT_FOUND` | 404 | Product not found |
| `BITRIX_UNAVAILABLE` | 502 | Bitrix24 unavailable |
| `BITRIX_ERROR` | 422 | Bitrix24 REST API error |
