## Проверить форму

`POST /v1/crm-forms/validate`

`POST /v1/crm-forms/:id/validate`

Проверяет конфигурацию CRM-формы без сохранения и возвращает список нарушений. Первый путь проверяет черновик новой формы, второй — изменения сохранённой формы с указанным ID.

## Параметры

| Параметр | Тип | Обяз. | Описание |
|----------|-----|:-----:|----------|
| `id` (path) | integer | нет | ID сохранённой формы — только для пути `POST /v1/crm-forms/:id/validate`. Список: [`GET /v1/crm-forms`](/docs/entities/crm-forms/list) |

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

Передавайте плоское тело или объект в `fields`: `{"fields":{"name":"Contact form"}}`. Массив в `fields` — секция полей формы в плоском теле. Объект в `fields` нельзя сочетать с другими свойствами верхнего уровня — это `400 INVALID_PARAMS`. Свойства формы и их значения проверяет портал.

Тело — те же свойства, что у [создания](/docs/entities/crm-forms/create) и [изменения](/docs/entities/crm-forms/update) формы. Для черновика передайте конфигурацию целиком. Для сохранённой формы — только изменяемые свойства, без `updatedTime`. Пустой объект `{}` проверяет форму в сохранённом виде.

| Поле | Тип | Обяз. | Описание |
|------|-----|:-----:|----------|
| `name` | string \| null | нет | Название формы. Черновик без `name` получает нарушение по этому полю |
| `crm` | object | нет | Привязка к CRM. |
| `crm.entityScheme` | integer | нет | Схема создаваемых записей CRM. Список: `data.entitySchemes` в [`GET /v1/crm-forms/configuration`](/docs/entities/crm-forms/configuration) |
| `active` | boolean | нет | Включена ли форма. Допустимость свойства проверяет портал |
| `languageId` | string \| null | нет | Язык формы. Список: `data.languages` в [`GET /v1/crm-forms/configuration`](/docs/entities/crm-forms/configuration) |
| `templateId` | string \| null | нет | Сценарий, из которого создана форма. Список: [Список сценариев](/docs/entities/crm-forms/scenarios) |
| `appearance` | object | нет | Оформление: заголовок `title`, описание `description`, подпись кнопки `buttonCaption` и другие свойства. |
| `fields` | array \| object | нет | Массив полей формы или объект с конфигурацией запроса |
| `fields[].name` | string | нет | Имя поля, например `LEAD_NAME`. Список: [`GET /v1/crm-forms/entity-fields`](/docs/entities/crm-forms/entity-fields) |
| `fields[].type` | string | нет | Тип поля. Список: `data.fieldTypes` в [`GET /v1/crm-forms/configuration`](/docs/entities/crm-forms/configuration) |
| `fields[].label` | string | нет | Подпись поля в форме |
| `fields[].required` | boolean | нет | Обязательно ли поле для отправки. Передавайте явно: без флага при сохранении ставится `true` |
| `fields[].multiple` | boolean | нет | Принимает ли поле несколько значений. Передавайте явно: без флага при сохранении ставится `true` |
| `responsible` | object | нет | Ответственные за результаты формы |
| `responsible.userIds` | array of integer | нет | ID ответственных. Список: [`GET /v1/users`](/docs/entities/users) |
| `agreements` | object | нет | Настройки соглашений в схеме Битрикс24 |
| `submission` | object | нет | Настройки после отправки. |
| `callback` | object | нет | Настройки обратного звонка. |
| `payment` | object | нет | Настройки оплаты. |
| `booking` | object | нет | Настройки бронирования. |
| `presetFields` | array | нет | Предустановленные значения полей |
| `dependencies` | array | нет | Зависимости между полями |
| `analytics` | object | нет | Настройки аналитики |
| `integrations` | object | нет | Настройки интеграций |
| `spamProtection` | object | нет | Защита от спама |

Справочник [Поля контракта формы](/docs/entities/crm-forms/fields) описывает метаданные только верхнего уровня. Имена вложенных свойств и исходные значения секций для сохранённой формы берите из полного ответа [Прочитать форму](/docs/entities/crm-forms/get). Секции передаются в схеме Битрикс24; доступность записи настроек определяет портал.

## Примеры

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

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/crm-forms/validate" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Форма обратной связи",
    "crm": { "entityScheme": 1 },
    "fields": [
      { "name": "LEAD_NAME", "type": "string", "label": "Имя", "required": false, "multiple": false },
      { "name": "LEAD_PHONE", "type": "phone", "label": "Телефон", "required": false, "multiple": false }
    ]
  }'
```

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

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/crm-forms/validate" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Форма обратной связи",
    "crm": { "entityScheme": 1 },
    "fields": [
      { "name": "LEAD_NAME", "type": "string", "label": "Имя", "required": false, "multiple": false },
      { "name": "LEAD_PHONE", "type": "phone", "label": "Телефон", "required": false, "multiple": false }
    ]
  }'
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/crm-forms/validate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Форма обратной связи',
    crm: { entityScheme: 1 },
    fields: [
      { name: 'LEAD_NAME', type: 'string', label: 'Имя', required: false, multiple: false },
      { name: 'LEAD_PHONE', type: 'phone', label: 'Телефон', required: false, multiple: false },
    ],
  }),
})

const { data } = await res.json()
if (!data.valid) console.log('Нарушения:', data.violations)
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/crm-forms/validate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Форма обратной связи',
    crm: { entityScheme: 1 },
    fields: [
      { name: 'LEAD_NAME', type: 'string', label: 'Имя', required: false, multiple: false },
      { name: 'LEAD_PHONE', type: 'phone', label: 'Телефон', required: false, multiple: false },
    ],
  }),
})

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

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

HTTP `200` на обоих путях, в том числе когда проверка не пройдена.

| Поле | Тип | Описание |
|------|-----|----------|
| `success` | boolean | `true` — проверка выполнена. Результат проверки — в `data.valid` |
| `data.valid` | boolean | `true` — нарушений нет, `false` — конфигурацию нужно исправить |
| `data.violations` | array | Нарушения. Пустой массив при `valid: true` |
| `data.violations[].field` | string | Путь к свойству с нарушением, например `name` |
| `data.violations[].message` | string | Текст нарушения |
| `meta.redacted` | array of string | Пути JSON, где заменены учётные данные текущего подключения |

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

Нарушений нет:

```json
{
  "success": true,
  "data": {
    "valid": true,
    "violations": []
  }
}
```

Проверка не пройдена — в черновике нет `name`:

```json
{
  "success": true,
  "data": {
    "valid": false,
    "violations": [
      {
        "field": "name",
        "message": "Name of the CRM form is required"
      }
    ]
  }
}
```

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

400 — объект в `fields` смешан с другим свойством верхнего уровня:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "Use either a flat body or {fields:{...}}"
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 404 | `ENTITY_NOT_FOUND` | Портал не нашёл запрошенную сущность или описание поля. Исходный код — `error.b24Code` |
| 400 | `INVALID_PARAMS` | `id` не положительное целое число, тело не JSON-объект или передан параметр строки запроса |
| 403 | `CRM_FORM_SYSTEM_IMMUTABLE` | Только путь с `id`: форма системная, её настройки не изменяются |
| 403 | `BITRIX_INSUFFICIENT_SCOPE` | У токена Битрикс24 нет необходимого скоупа |
| 409 | `CRM_FORM_REST_NOT_ENABLED` | На портале выключены методы CRM-форм |
| 403 | `BITRIX_ACCESS_DENIED` | Битрикс24 отказал в доступе: у пользователя нет права на изменение CRM-форм |
| 403 | `SCOPE_DENIED` | Ключу не хватает скоупа `crm` |
| 401 | `MISSING_API_KEY` | Не передан `X-Api-Key` |
| 401 | `TOKEN_MISSING` | У ключа нет токенов доступа к Битрикс24 |
| 422 | `BITRIX_ERROR` | Другой отказ Битрикс24. Исходное сообщение сохраняется в `error.message` |
| 502 | `BITRIX_UNAVAILABLE` | Битрикс24 недоступен или вернул ответ неверного вида |

Ошибки портала содержат исходный код в `error.b24Code` и ошибки полей в `error.validation`, если они переданы. Коды `CRM_FORM_*` сохраняют HTTP-статус, код и сообщение. Общие ответы 429, 502 и 503 — [Лимиты и оптимизация](/docs/optimization). Полный список общих ошибок API — [Ошибки](/docs/errors).

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

**Работает с ключом только для чтения.** Проверка ничего не сохраняет и не меняет `updatedTime` формы, поэтому доступна и такому ключу.

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

- [Создать форму](/docs/entities/crm-forms/create)
- [Изменить форму](/docs/entities/crm-forms/update)
- [Получить форму](/docs/entities/crm-forms/get)
- [Поля контракта формы](/docs/entities/crm-forms/fields)
- [Получить конфигурацию конструктора](/docs/entities/crm-forms/configuration)
- [Список полей сущностей](/docs/entities/crm-forms/entity-fields)
- [Лимиты и оптимизация](/docs/optimization)
