## Заменить стадии воронки

`PUT /v1/deal-categories/:categoryId/stages`

`PUT /v1/categories/:entityTypeId/:categoryId/stages`

Заменяет изменяемый набор стадий воронки сделок или смарт-процесса. Порядок элементов массива задаёт порядок стадий.

> **Метод требует обновления CRM после `26.2200.0`. Номер выпущенной версии ещё не определён. Доступен не на всех порталах Битрикс24. Возможность должен включить администратор.**

**Внимание:** стадии, не включённые в замену, могут быть удалены. Используйте ключ `READWRITE` со скоупом `crm` и правами на управление стадиями воронки.

## Параметры

| Параметр | Тип | Обяз. | По умолч. | Описание |
|----------|-----|-------|-----------|----------|
| `categoryId` (path) | number | да | — | Неотрицательное безопасное целое число. `0` — основная воронка сделок. ID из [Воронок сделок](/docs/entities/deal-categories/list) или [Воронок](/docs/entities/categories/list) |
| `entityTypeId` (path) | number | да, для второго пути | — | `2` для сделок или динамический тип из [Смарт-процессов](/docs/entities/smart-processes/list). Другие фиксированные типы CRM не принимаются |

## Поля запроса (body)

| Поле | Тип | Обяз. | Описание |
|------|-----|-------|----------|
| `stages` | array | да | Новый упорядоченный набор, не более 50 элементов. Пустой массив удаляет доступные для удаления стадии с проверкой прав и использования |
| `stages[].stageId` | string \| null | нет | Полный ID существующей стадии из поля `statusId` в [Статусах](/docs/entities/statuses/list) или предыдущего ответа замены. Без поля или с `null` создаётся стадия |
| `stages[].name` | string | да | Название стадии, до 100 символов |
| `stages[].color` | string | нет | `#RRGGBB` или пустая строка для удаления цвета. Без поля существующий цвет сохраняется |
| `stages[].description` | string | нет | Описание стадии |

## Примеры

Замените `29` на ID своей тестовой воронки.

### curl — личный ключ

```bash
curl -X PUT "https://vibecode.bitrix24.tech/v1/deal-categories/29/stages" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"stages":[{"name":"VIBE-PROBE First"},{"name":"VIBE-PROBE Second"}]}'
```

### curl — OAuth-приложение

```bash
curl -X PUT "https://vibecode.bitrix24.tech/v1/deal-categories/29/stages" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"stages":[{"name":"VIBE-PROBE First"},{"name":"VIBE-PROBE Second"}]}'
```

### JavaScript — личный ключ

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/deal-categories/29/stages', {
  method: 'PUT',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"stages":[{"name":"VIBE-PROBE First"},{"name":"VIBE-PROBE Second"}]}),
})
const result = await res.json()
console.log(result)
```

### JavaScript — OAuth-приложение

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/deal-categories/29/stages', {
  method: 'PUT',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"stages":[{"name":"VIBE-PROBE First"},{"name":"VIBE-PROBE Second"}]}),
})
const result = await res.json()
console.log(result)
```

## Поля ответа

| Поле | Тип | Описание |
|------|-----|----------|
| `success` | boolean | `true` при успехе |
| `data` | array | Стадии воронки после замены |
| `data[].stageId` | string | Полный ID стадии. Источник — этот ответ или поле `statusId` в [Статусах](/docs/entities/statuses/list) |
| `data[].categoryId` | number | ID воронки из [Списка воронок](/docs/entities/deal-categories/list) |
| `data[].name` | string | Название стадии |
| `data[].sort` | number | Порядок сортировки |
| `data[].semantics` | string | `process`, `success` или `failure` |
| `data[].color` | string | Цвет или пустая строка |
| `data[].isSystem` | boolean | Признак системной стадии |
| `data[].description` | string | Описание стадии |

## Пример ответа

HTTP 200.

```json
{
  "success": true,
  "data": [
    {
      "stageId": "C29:NEW",
      "categoryId": 29,
      "name": "Новая",
      "sort": 10,
      "semantics": "process",
      "color": "#1F86FF",
      "isSystem": true,
      "description": ""
    },
    {
      "stageId": "C29:UC_975XX9",
      "categoryId": 29,
      "name": "VIBE-PROBE First",
      "sort": 20,
      "semantics": "process",
      "color": "",
      "isSystem": false,
      "description": ""
    },
    {
      "stageId": "C29:UC_8U03YB",
      "categoryId": 29,
      "name": "VIBE-PROBE Second",
      "sort": 30,
      "semantics": "process",
      "color": "",
      "isSystem": false,
      "description": ""
    },
    {
      "stageId": "C29:WON",
      "categoryId": 29,
      "name": "Сделка успешна",
      "sort": 40,
      "semantics": "success",
      "color": "#7BD500",
      "isSystem": true,
      "description": ""
    },
    {
      "stageId": "C29:LOSE",
      "categoryId": 29,
      "name": "Сделка провалена",
      "sort": 50,
      "semantics": "failure",
      "color": "#FF5752",
      "isSystem": true,
      "description": ""
    },
    {
      "stageId": "C29:APOLOGY",
      "categoryId": 29,
      "name": "Анализ причины провала",
      "sort": 60,
      "semantics": "failure",
      "color": "#FF5752",
      "isSystem": false,
      "description": ""
    }
  ]
}
```

## Пример ответа при ошибке

400 — нарушена структура тела замены:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "Use a nonnegative categoryId and a stages array with name and optional stageId, color and description"
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 400 | `INVALID_PARAMS` | Неверный формат пути или тела запроса |
| 400 | `UNKNOWN_FILTER_FIELD` | Неизвестный или повторяющийся параметр запроса |
| 404 | `ENTITY_NOT_FOUND` | Воронка или стадия не найдена |
| 403 | `BITRIX_ACCESS_DENIED` | Недостаточно прав в Битрикс24 |
| 403 | `SCOPE_DENIED` | Ключ не имеет скоупа `crm` |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | Запись запрещена ключу `READONLY` |
| 401 | `TOKEN_MISSING` | У ключа нет настроенного доступа к Битрикс24 |
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |
| 422 | `METHOD_NOT_YET_AVAILABLE` | Возможность не включена или метод недоступен на этом портале. `error.release` указывает обновление |
| 502 | `BITRIX_UNAVAILABLE` | Получен некорректный ответ Битрикс24 |

Другие отказы Битрикс24 сохраняют HTTP-статус, код и сообщение с удалением учётных данных. Общие ошибки API — [Ошибки](/docs/errors).

## Известные особенности

Системные и финальные стадии сохраняются, даже если их нет в массиве. Изменение таких стадий и удаление стадии, занятой записями, запрещены. Набор заменяется в одной транзакции без переноса записей.

После таймаута или обрыва соединения не повторяйте запрос вслепую: замена могла завершиться, а элементы без `stageId` запрашивают создание стадий. Перед повторной отправкой прочитайте текущие стадии.

## Смотрите также

- [Воронки сделок](/docs/entities/deal-categories)
- [Воронки](/docs/entities/categories)
- [Статусы](/docs/entities/statuses)
