[{"data":1,"prerenderedAt":15},["ShallowReactive",2],{"docs-entities\u002Fcrm-forms\u002Fmanagement":3,"docs-tabs-entities\u002Fcrm-forms\u002Fmanagement":6},{"content":4,"lastmod":5},"# Form management\n\nCreate, read, update and delete CRM forms, validate a configuration without saving it and toggle whether a form is active.\n\nBitrix24 API: `crm.form.*`\nScope: `crm`\n\n## Operations\n\n- [Create a form](.\u002Fcreate.md) — `POST \u002Fv1\u002Fcrm-forms`\n- [List forms](.\u002Flist.md) — `GET \u002Fv1\u002Fcrm-forms`\n- [Get a form](.\u002Fget.md) — `GET \u002Fv1\u002Fcrm-forms\u002F:id`\n- [Update a form](.\u002Fupdate.md) — `PATCH \u002Fv1\u002Fcrm-forms\u002F:id`\n- [Delete a form](.\u002Fdelete.md) — `DELETE \u002Fv1\u002Fcrm-forms\u002F:id`\n- [Validate a form](.\u002Fvalidate.md) — `POST \u002Fv1\u002Fcrm-forms\u002Fvalidate`\n- [Activate a form](.\u002Factivate.md) — `POST \u002Fv1\u002Fcrm-forms\u002F:id\u002Factivate`\n- [Deactivate a form](.\u002Fdeactivate.md) — `POST \u002Fv1\u002Fcrm-forms\u002F:id\u002Fdeactivate`\n\n## Typical scenario\n\n1. Validate a draft without saving it: `POST \u002Fv1\u002Fcrm-forms\u002Fvalidate`.\n2. Create the form: `POST \u002Fv1\u002Fcrm-forms`. Use a flat body or `{fields:{...}}`. If the response contains `meta.warnings`, creation succeeded: GET the form instead of repeating POST. If `CRM_FORM_PARTIALLY_CREATED` is returned, the form exists; its ID is in `error.id`. Read it, then correct or delete it. Do not repeat creation.\n3. To update a form, read it with `GET \u002Fv1\u002Fcrm-forms\u002F:id`, keep `updatedTime` and pass it at the root of `PATCH \u002Fv1\u002Fcrm-forms\u002F:id`, with flat settings or an object-valued `fields` wrapper. A partial projection is not a full configuration. Do not save a response marked with `meta.redacted` back as the complete form.\n4. Activate and deactivate the form with separate `activate` and `deactivate` calls. Keep the returned `active` and `updatedTime`. After a write that returns a read warning, GET the form before the next change.\n\n## See also\n\n- [Builder dictionaries](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fbuilder)\n- [Publishing and results](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fpublishing)\n- [CRM forms](\u002Fdocs\u002Fentities\u002Fcrm-forms)\n","2026-11-06",{"create.md":7,"list.md":8,"get.md":9,"update.md":10,"delete.md":11,"validate.md":12,"activate.md":13,"deactivate.md":14},"## Create a form\n\n`POST \u002Fv1\u002Fcrm-forms`\n\nCreates a CRM form with fields, a CRM binding, responsible users and result texts.\n\n## Request fields (body)\n\nPass either a flat body or an object in `fields`: `{\"fields\":{\"name\":\"VIBE-PROBE 777758 parity\"}}`. An array in `fields` is the form field section of a flat body. Do not combine an object in `fields` with other top-level properties — this returns `400 INVALID_PARAMS`. Bitrix24 validates the form properties and values.\n\nBefore creating, you can check a draft without saving it: [Validate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fvalidate).\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|----------|\n| `name` | string | yes | Form name in the forms list |\n| `crm` | object | yes | CRM binding. Take nested settings from the configuration of a specific form |\n| `crm.entityScheme` | integer | yes | Scheme of the CRM records the form creates. List: `data.entitySchemes` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `active` | boolean | no | Whether the form is enabled. Defaults to `true`. The state also has dedicated operations: [activation](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Factivate) and [deactivation](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fdeactivate) |\n| `languageId` | string \\| null | no | Form language. List: `data.languages` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `templateId` | string \\| null | no | Scenario the form was created from. List: [List scenarios](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fscenarios) |\n| `appearance` | object | no | Appearance: `title`, `description`, button caption `buttonCaption` and other properties |\n| `fields` | array \\| object | no | Form fields as an array, or a request envelope as an object |\n| `fields[].name` | string | no | Field name, for example `LEAD_NAME`. List: [`GET \u002Fv1\u002Fcrm-forms\u002Fentity-fields`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fentity-fields) |\n| `fields[].type` | string | no | Field type. List: `data.fieldTypes` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `fields[].label` | string | no | Field label in the form |\n| `fields[].required` | boolean | no | Whether the field is required for submission. Pass it explicitly: without the flag, `true` is saved |\n| `fields[].multiple` | boolean | no | Whether the field accepts multiple values. Pass it explicitly: without the flag, `true` is saved |\n| `responsible` | object | no | Users responsible for the form results |\n| `responsible.userIds` | array of integer | no | IDs of responsible users. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers) |\n| `agreements` | object | no | Agreement settings in the Bitrix24 format |\n| `submission` | object | no | Post-submission settings: texts and redirect URLs on success and on error |\n| `callback` | object | no | Callback settings |\n| `payment` | object | no | Payment settings |\n| `booking` | object | no | Booking settings |\n| `presetFields` | array | no | Preset field values |\n| `dependencies` | array | no | Dependencies between fields |\n| `analytics` | object | no | Analytics settings |\n| `integrations` | object | no | Integration settings |\n| `spamProtection` | object | no | Spam protection settings |\n\nThe [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) reference describes top-level metadata only. To create a form based on an existing one, take the names of nested properties and the initial section values from the full [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) response. Sections are passed in the Bitrix24 format; Bitrix24 decides which settings can be written.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"name\": \"VIBE-PROBE 777758 parity\",\n    \"active\": false,\n    \"crm\": { \"entityScheme\": 1 },\n    \"fields\": [\n      { \"name\": \"LEAD_NAME\", \"type\": \"string\", \"required\": false, \"multiple\": false }\n    ]\n  }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"name\": \"VIBE-PROBE 777758 parity\",\n    \"active\": false,\n    \"crm\": { \"entityScheme\": 1 },\n    \"fields\": [\n      { \"name\": \"LEAD_NAME\", \"type\": \"string\", \"required\": false, \"multiple\": false }\n    ]\n  }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    name: 'VIBE-PROBE 777758 parity',\n    active: false,\n    crm: { entityScheme: 1 },\n    fields: [\n      { name: 'LEAD_NAME', type: 'string', required: false, multiple: false },\n    ],\n  }),\n})\n\nconst { data } = await res.json()\nconsole.log('Form ID:', data.id, 'updatedTime:', data.updatedTime)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    name: 'VIBE-PROBE 777758 parity',\n    active: false,\n    crm: { entityScheme: 1 },\n    fields: [\n      { name: 'LEAD_NAME', type: 'string', required: false, multiple: false },\n    ],\n  }),\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nHTTP `201`. The response is the saved form, re-read after creation. Form properties other than `id` are present only when this read succeeds.\n\n| Field | Type | Description |\n|------|-----|----------|\n| `success` | boolean | `true` on success |\n| `data` | object | The created form in the same format as [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget). Top-level property metadata: [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) |\n| `data.id` | integer | ID of the created form |\n| `data.name` | string | Form name |\n| `data.active` | boolean \\| null | Whether the form is enabled |\n| `data.updatedTime` | string \\| null | Time of the last change. Passed to [`PATCH \u002Fv1\u002Fcrm-forms\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fupdate) |\n| `data.fields` | array | Form fields as saved, including `required` and `multiple` |\n| `meta.warnings` | array | Present when the saved state could not be read |\n| `meta.redacted` | array of string | JSON paths where current connection credentials were replaced. Do not save this representation back as a complete configuration |\n\nIf the write succeeds but the follow-up read fails, the response stays successful: `201` with only `data.id` and `meta.warnings[].code: \"CRM_FORM_READBACK_FAILED\"`. GET the form before another write to obtain its current `updatedTime`. Do not repeat the successful write.\n\n## Response example\n\nThe example is abbreviated. Take nested property names and values from the full [GET response](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) for your configured form. [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) describes top-level metadata only.\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 91,\n    \"code\": \"91\",\n    \"name\": \"VIBE-PROBE 777758 parity\",\n    \"active\": false,\n    \"system\": false,\n    \"createdTime\": \"2026-11-05T08:16:55Z\",\n    \"updatedTime\": \"2026-11-05T08:16:55Z\",\n    \"crm\": {\n      \"entityScheme\": 1,\n      \"duplicateMode\": \"\",\n      \"dealCategoryId\": null,\n      \"dealDuplicateControlEnabled\": false,\n      \"smartProcessCategoryId\": null,\n      \"smartProcessDuplicateControlEnabled\": false\n    },\n    \"fields\": [\n      {\n        \"name\": \"LEAD_NAME\",\n        \"type\": \"string\",\n        \"label\": null,\n        \"sort\": 10,\n        \"required\": false,\n        \"multiple\": false,\n        \"placeholder\": null,\n        \"valueType\": null,\n        \"value\": null\n      }\n    ],\n    \"agreements\": {\n      \"enabled\": false,\n      \"items\": []\n    }\n  }\n}\n```\n\n## Error response example\n\n400 — an object in `fields` is combined with another top-level property:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"INVALID_PARAMS\",\n    \"message\": \"Use either a flat body or {fields:{...}}\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|----------|\n| 400 | `INVALID_PARAMS` | The body is not a JSON object, or a query string parameter was passed |\n| 400 | `INVALID_PARAMS` | Bitrix24 rejected the configuration, for example `crm.entityScheme` was not passed. Violations are listed in `error.validation` |\n| 400 | `CRM_FORM_PARTIALLY_CREATED` | The form exists: `error.id` is its ID, `error.b24Code` is the original error code, and `error.validation` describes failed sections. GET the form, then correct or delete it. Do not repeat creation |\n| 402 | `CRM_FORM_WRITE_RESTRICTED` | The Bitrix24 plan (free or demo) does not allow writing CRM forms |\n| 402 | `CRM_FORM_ACTIVATION_LIMIT_REACHED` | The form is created as enabled, and the active form limit is reached. The limit is `data.limits.activeForms` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only. A key with write access is required |\n| 403 | `BITRIX_INSUFFICIENT_SCOPE` | The Bitrix24 token lacks the required scope |\n| 404 | `ENTITY_NOT_FOUND` | Bitrix24 did not find the requested entity or field descriptor. The original code is in `error.b24Code` |\n| 409 | `CRM_FORM_REST_NOT_ENABLED` | The CRM form methods are disabled on the Bitrix24 account |\n| 403 | `BITRIX_ACCESS_DENIED` | Bitrix24 denied access: the user has no permission to change CRM forms |\n| 403 | `SCOPE_DENIED` | The key lacks the `crm` scope |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` was not passed |\n| 401 | `TOKEN_MISSING` | The key has no Bitrix24 access tokens |\n| 422 | `BITRIX_ERROR` | Any other Bitrix24 refusal. The original message is kept in `error.message` |\n| 500 | `CRM_FORM_SIDE_EFFECT_FAILED` | The form is already saved, but a subsequent step on the Bitrix24 side failed. `error.id` is the ID of the created form. Read the form before retrying |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a malformed response. The form may already be created — find it in the [forms list](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist) before retrying |\n\nBitrix24 errors include the original code in `error.b24Code` and field violations in `error.validation` when provided. `CRM_FORM_*` codes retain their HTTP status, code and message. Common 429, 502 and 503 responses: [Limits and optimization](\u002Fdocs\u002Foptimization). Full list of common API errors: [Errors](\u002Fdocs\u002Ferrors).\n\n## See also\n\n- [Validate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fvalidate)\n- [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget)\n- [Update a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fupdate)\n- [Activate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Factivate)\n- [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields)\n- [Get the builder configuration](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration)\n- [List entity fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fentity-fields)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n","## List forms\n\n`GET \u002Fv1\u002Fcrm-forms`\n\nFinds CRM forms in the Bitrix24 account by activity, name, code, CRM scheme, responsible user or dates, so you can get the ID of the form you need.\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|----------|-----|-----------|----------|\n| `id` (query) | integer \\| integer[] | — | Form IDs. Repeat the parameter: `?id=1&id=3`. IDs come from this list |\n| `active` (query) | boolean | — | Form activity. Omit to return both active and inactive forms |\n| `name` (query) | string | — | Exact form name, including commas. Repeat the parameter for several names |\n| `code` (query) | string | — | Exact symbolic code. Repeat the parameter for several codes |\n| `entityScheme` (query) | number | — | Alias for `crm.entityScheme`. Values: `entitySchemes` in [builder configuration](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration). Several values may be comma-separated |\n| `responsibleUserId` (query) | number | — | Alias for `responsible.userIds`. IDs: [List employees](\u002Fdocs\u002Fentities\u002Fusers\u002Flist). Several IDs may be comma-separated |\n| `filter` (query) | object | — | Filter by form properties. Top-level metadata: [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields). [Filtering syntax](\u002Fdocs\u002Ffiltering). Example: `?filter[id][$in]=1,3`, date range: `?filter[updatedTime][$gte]=2023-01-01T00:00:00Z`. Property names and operators are validated by Bitrix24 |\n| `select` (query) | string | — | Comma-separated properties and nested paths, such as `id,name,active,templateId,crm.entityScheme,responsible.userIds,updatedTime` |\n| `order` (query) | object | — | Sort: `?order[name]=desc`. Use either `order[...]` or `sort`. Using both returns `400 INVALID_PARAMS` |\n| `sort` (query) | string | — | Sort shorthand: `?sort=-name`; a leading minus means descending order. Bitrix24 validates sort properties and directions |\n| `limit` (query) | number | — | Page size. Bitrix24 validates the value |\n| `offset` (query) | number | — | Number of forms to skip. Bitrix24 validates the value |\n\nPagination. One request reads one page. Without `limit` and `offset`, Bitrix24 uses its own pagination defaults. Pagination metadata is included only when returned by Bitrix24. To request the next page, pass `limit` and increase `offset` by that value.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms?limit=2\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms?limit=2\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms?limit=2', {\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { data, meta } = await res.json()\nfor (const form of data) console.log(form.id, form.name)\nconst mayHaveNextPage = data.length === 2\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms?limit=2', {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data, meta } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|----------|\n| `success` | boolean | `true` on success |\n| `data` | array | Forms on the page, preserving their properties. Top-level property metadata: [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) |\n| `meta` | object | Optional pagination metadata returned by Bitrix24 |\n| `meta.redacted` | string[] | Present only when the current connection's credentials are found in the content. `JSON Pointer` paths identify replaced values |\n\nWithout `select`, each form has 11 scalar properties: `id`, `code`, `name`, `active`, `system`, `languageId`, `templateId`, `createdTime`, `updatedTime`, `activeChangedById`, `activeChangedTime`. Target entities and responsible users require an explicit `select`. `activeChangedById` identifies the author of the activity change, not the responsible user.\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": [\n    {\n      \"id\": 1,\n      \"code\": \"1_kontaktnye_dannye\",\n      \"name\": \"Contact details\",\n      \"active\": true,\n      \"system\": true,\n      \"languageId\": \"ru\",\n      \"templateId\": \"light\",\n      \"createdTime\": \"2020-04-22T06:13:05Z\",\n      \"updatedTime\": \"2020-04-22T06:13:05Z\",\n      \"activeChangedById\": 1,\n      \"activeChangedTime\": \"2020-04-22T06:13:05Z\"\n    },\n    {\n      \"id\": 3,\n      \"code\": \"3_obratnaya_svyaz\",\n      \"name\": \"Feedback form\",\n      \"active\": true,\n      \"system\": true,\n      \"languageId\": \"ru\",\n      \"templateId\": \"light\",\n      \"createdTime\": \"2020-04-22T06:13:05Z\",\n      \"updatedTime\": \"2020-04-22T06:13:05Z\",\n      \"activeChangedById\": 1,\n      \"activeChangedTime\": \"2020-04-22T06:13:05Z\"\n    }\n  ]\n}\n```\n\nLive response from a Russian-language portal: `code` and `languageId` are portal values returned as stored. `code` is the exact value for the `?code=` filter, and another portal has its own codes. Only the display `name` appears here in English.\n\n## Error response example\n\n400 — invalid `limit`, here `?limit=abc`:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"INVALID_PARAMS\",\n    \"message\": \"Cannot parse pagination parameter `{\\\"limit\\\":\\\"abc\\\"}`\",\n    \"b24Code\": \"BITRIX_REST_V3_EXCEPTION_INVALIDPAGINATIONEXCEPTION\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|----------|\n| 400 | `INVALID_PARAMS` | Malformed `filter`, `select`, `order` or `sort` structure |\n| 400 | `INVALID_PARAMS` | Both `order[...]` and `sort` were passed |\n| 400 | `INVALID_PARAMS` | Bitrix24 rejected a filter, sort or pagination value. The original code is in `error.b24Code`. Field errors are in `error.validation` |\n| 403 | `BITRIX_ACCESS_DENIED` | The Bitrix24 user lacks permission to access forms |\n| 403 | `BITRIX_INSUFFICIENT_SCOPE` | The Bitrix24 token lacks the required scope |\n| 404 | `ENTITY_NOT_FOUND` | Bitrix24 did not find a requested entity or field descriptor. The original code is in `error.b24Code` |\n| 409 | `CRM_FORM_REST_NOT_ENABLED` | The CRM form REST methods are unavailable on this Bitrix24 account. This does not mean that an individual form is missing |\n| 400–599 | `CRM_FORM_*` | Rejection under form rules. The code and HTTP status are preserved. The original code is in `error.b24Code` |\n| 422 | `BITRIX_ERROR` | Another Bitrix24 rejection. The reason is in `error.message`. The original code is in `error.b24Code` |\n| 429 | `RATE_LIMITED` | Request rate exceeded. Follow the `Retry-After` header |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 returned an unexpected response shape |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable: a server error or a dropped connection |\n| 503 | `BITRIX_TIMEOUT` | Bitrix24 did not respond in time. The read can be retried |\n| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |\n| 401 | `TOKEN_MISSING` | The key has no configured Bitrix24 credentials |\n| 403 | `SCOPE_DENIED` | The Vibecode API key lacks the `crm` scope |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## See also\n\n- [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget)\n- [Create a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fcreate)\n- [Get the builder configuration](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration)\n- [CRM forms](\u002Fdocs\u002Fentities\u002Fcrm-forms)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n","## Get a form\n\n`GET \u002Fv1\u002Fcrm-forms\u002F:id`\n\nReads the settings of one CRM form by ID to learn the field names before submitting visitor data or to prepare a form update.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|----------|\n| `id` (path) | integer | yes | Form ID. List: [List forms](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist) |\n| `select` (query) | string | no | Comma-separated properties or nested paths. Without it, all 11 scalar properties and 14 sections are requested |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F91\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F91\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F91', {\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { data } = await res.json()\nfor (const field of data.fields) console.log(field.name, field.type, field.required)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F91', {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|----------|\n| `success` | boolean | `true` on success |\n| `data` | object | Form properties as returned by Bitrix24, restricted to the requested `select`. Top-level property metadata: [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) |\n| `meta.redacted` | string[] | Present only when credentials of the current connection are found in the content. `JSON Pointer` paths identify replaced values. Do not save this representation back as a complete configuration |\n\nThe 14 sections are `appearance`, `crm`, `dependencies`, `presetFields`, `responsible`, `agreements`, `submission`, `payment`, `callback`, `booking`, `analytics`, `spamProtection`, `integrations`, `fields`. Content and field properties are preserved, including strings that resemble credentials. Only exact occurrences of the current connection's credentials are replaced.\n\nTake nested property names and their values from the full `GET \u002Fv1\u002Fcrm-forms\u002F:id` response for a specific configured form. The metadata reference describes only the top level, not the structure of nested sections.\n\n## Response example\n\nThe main properties are shown. The full response also includes the other properties from [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields).\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 91,\n    \"name\": \"VIBE-PROBE 777758 parity\",\n    \"active\": false,\n    \"updatedTime\": \"2026-11-05T08:16:55Z\",\n    \"crm\": {\n      \"entityScheme\": 1,\n      \"duplicateMode\": \"\",\n      \"dealCategoryId\": null,\n      \"dealDuplicateControlEnabled\": false,\n      \"smartProcessCategoryId\": null,\n      \"smartProcessDuplicateControlEnabled\": false\n    },\n    \"responsible\": {\n      \"userIds\": [],\n      \"checkWorkTime\": false\n    },\n    \"agreements\": {\n      \"enabled\": false,\n      \"items\": []\n    },\n    \"fields\": [\n      {\n        \"name\": \"LEAD_NAME\",\n        \"type\": \"string\",\n        \"label\": null,\n        \"sort\": 10,\n        \"required\": false,\n        \"multiple\": false,\n        \"placeholder\": null,\n        \"valueType\": null,\n        \"value\": null\n      }\n    ]\n  }\n}\n```\n\n## Error response example\n\n404 — no form with this `id`:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Record with ID = `999999999` not found\",\n    \"b24Code\": \"BITRIX_REST_V3_EXCEPTION_ENTITYNOTFOUNDEXCEPTION\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|----------|\n| 400 | `INVALID_PARAMS` | `id` is not a positive safe integer |\n| 400 | `INVALID_PARAMS` | An unknown query parameter was passed or `select` has an invalid structure |\n| 400 | `INVALID_PARAMS` | Bitrix24 rejected the projection. The original code is in `error.b24Code` |\n| 404 | `ENTITY_NOT_FOUND` | No form with this `id`. The original code is in `error.b24Code` |\n| 403 | `BITRIX_ACCESS_DENIED` | The Bitrix24 user lacks permission to access forms |\n| 403 | `BITRIX_INSUFFICIENT_SCOPE` | The Bitrix24 token lacks the required scope |\n| 409 | `CRM_FORM_REST_NOT_ENABLED` | The CRM form REST methods are unavailable on this Bitrix24 account. This does not mean that an individual form is missing |\n| 400–599 | `CRM_FORM_*` | Rejection under form rules. The code and HTTP status are preserved. The original code is in `error.b24Code` |\n| 422 | `BITRIX_ERROR` | Another Bitrix24 rejection. The reason is in `error.message`. The original code is in `error.b24Code` |\n| 429 | `RATE_LIMITED` | Request rate exceeded. Follow the `Retry-After` header |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 returned an unexpected response shape |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable: a server error or a dropped connection |\n| 503 | `BITRIX_TIMEOUT` | Bitrix24 did not respond in time. The read can be retried |\n| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |\n| 401 | `TOKEN_MISSING` | The key has no configured Bitrix24 credentials |\n| 403 | `SCOPE_DENIED` | The Vibecode API key lacks the `crm` scope |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\nReading the form makes one request. Fetch value options for CRM fields separately from [List entity fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fentity-fields). They are not added to `fields[]` automatically.\n\n## See also\n\n- [List forms](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist)\n- [Update a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fupdate)\n- [Submit visitor data](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fresults)\n- [Get the builder configuration](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration)\n- [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields)\n- [CRM forms](\u002Fdocs\u002Fentities\u002Fcrm-forms)\n","## Update a form\n\n`PATCH \u002Fv1\u002Fcrm-forms\u002F:id`\n\nChanges the settings of a saved CRM form: name, fields, CRM binding, responsible users and texts.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|----------|\n| `id` (path) | integer | yes | Form ID. List: [`GET \u002Fv1\u002Fcrm-forms`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist) |\n\n## Request fields (body)\n\nPass either a flat body or an object in `fields`: `{\"fields\":{\"name\":\"Contact form\"}}`. In a flat body, an array in `fields` is the list of form fields. Do not combine an object in `fields` with other top-level properties except `updatedTime` — this returns `400 INVALID_PARAMS`. Bitrix24 validates the form properties and values.\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|----------|\n| `updatedTime` | string | yes | Current form version — `data.updatedTime` from [`GET \u002Fv1\u002Fcrm-forms\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) or from the response of the previous write |\n| `name` | string \\| null | no | Form name in the forms list |\n| `languageId` | string \\| null | no | Form language. List: `data.languages` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `templateId` | string \\| null | no | Scenario the form was created from. List: [List scenarios](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fscenarios) |\n| `crm` | object | no | CRM binding |\n| `crm.entityScheme` | integer | no | Scheme of the CRM records the form creates. List: `data.entitySchemes` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `appearance` | object | no | Appearance: `title`, `description`, button caption `buttonCaption` and other properties |\n| `fields` | array \\| object | no | Form fields as an array, or a request envelope as an object |\n| `fields[].name` | string | no | Field name, for example `LEAD_NAME`. List: [`GET \u002Fv1\u002Fcrm-forms\u002Fentity-fields`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fentity-fields) |\n| `fields[].type` | string | no | Field type. List: `data.fieldTypes` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `fields[].label` | string | no | Field label in the form |\n| `fields[].required` | boolean | no | Whether the field is required for submission. Pass it explicitly: without the flag, `true` is saved |\n| `fields[].multiple` | boolean | no | Whether the field accepts multiple values. Pass it explicitly: without the flag, `true` is saved |\n| `responsible` | object | no | Users responsible for the form results |\n| `responsible.userIds` | array of integer | no | IDs of responsible users. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers) |\n| `agreements` | object | no | Agreement settings in the Bitrix24 format |\n| `submission` | object | no | Post-submission settings: texts and redirect URLs on success and on error |\n| `callback` | object | no | Callback settings |\n| `payment` | object | no | Payment settings |\n| `booking` | object | no | Booking settings |\n| `presetFields` | array | no | Preset field values |\n| `dependencies` | array | no | Dependencies between fields |\n| `analytics` | object | no | Analytics settings |\n| `integrations` | object | no | Integration settings |\n| `spamProtection` | object | no | Spam protection settings |\n\nThe [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) reference describes top-level metadata only. Take the names of nested properties and the current section values of a saved form from the full [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) response. Sections are passed in the Bitrix24 format; Bitrix24 decides which settings can be written.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F91\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"updatedTime\": \"2026-11-05T08:16:55Z\",\n    \"name\": \"VIBE-PROBE 777758 flat, companies\"\n  }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F91\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"updatedTime\": \"2026-11-05T08:16:55Z\",\n    \"name\": \"VIBE-PROBE 777758 flat, companies\"\n  }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F91', {\n  method: 'PATCH',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    updatedTime: '2026-11-05T08:16:55Z',\n    name: 'VIBE-PROBE 777758 flat, companies',\n  }),\n})\n\nconst { data } = await res.json()\nconsole.log('New version:', data.updatedTime)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F91', {\n  method: 'PATCH',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    updatedTime: '2026-11-05T08:16:55Z',\n    name: 'VIBE-PROBE 777758 flat, companies',\n  }),\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nHTTP `200`. The response is the saved form, re-read after the change. Form properties other than `id` are present only when this read succeeds.\n\n| Field | Type | Description |\n|------|-----|----------|\n| `success` | boolean | `true` on success |\n| `data` | object | The updated form in the same format as [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget). Top-level property metadata: [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) |\n| `data.id` | integer | Form ID |\n| `data.name` | string | Form name |\n| `data.updatedTime` | string \\| null | New form version. Pass it in the next write request |\n| `data.fields` | array | Form fields as saved |\n| `meta.warnings` | array | Present when the saved state could not be read |\n| `meta.redacted` | array of string | JSON paths where current connection credentials were replaced. Do not save this representation back as a complete configuration |\n\nIf the write succeeds but the follow-up read fails, the response stays successful: `200` with only `data.id` and `meta.warnings[].code: \"CRM_FORM_READBACK_FAILED\"`. Before the next write, re-read the form with GET to obtain its current `updatedTime`. Do not repeat the successful write.\n\n## Response example\n\nThe example is abbreviated. Take nested property names and values from the full [GET response](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) for your configured form. [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) describes top-level metadata only.\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 91,\n    \"code\": \"91\",\n    \"name\": \"VIBE-PROBE 777758 flat, companies\",\n    \"active\": false,\n    \"system\": false,\n    \"createdTime\": \"2026-11-05T08:16:55Z\",\n    \"updatedTime\": \"2026-11-05T08:25:29Z\",\n    \"crm\": {\n      \"entityScheme\": 1,\n      \"duplicateMode\": \"\",\n      \"dealCategoryId\": null,\n      \"dealDuplicateControlEnabled\": false,\n      \"smartProcessCategoryId\": null,\n      \"smartProcessDuplicateControlEnabled\": false\n    },\n    \"fields\": [\n      {\n        \"name\": \"LEAD_NAME\",\n        \"type\": \"string\",\n        \"label\": null,\n        \"sort\": 10,\n        \"required\": false,\n        \"multiple\": false,\n        \"placeholder\": null,\n        \"valueType\": null,\n        \"value\": null\n      }\n    ],\n    \"agreements\": {\n      \"enabled\": false,\n      \"items\": []\n    }\n  }\n}\n```\n\n## Error response example\n\n409 — the form changed after it was read; the passed `updatedTime` is outdated:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CRM_FORM_VERSION_MISMATCH\",\n    \"message\": \"The CRM form version is outdated. Changes were not saved. Get the form again and retry the request\",\n    \"b24Code\": \"CRM_FORM_VERSION_MISMATCH\",\n    \"currentUpdatedTime\": \"2026-11-05T08:25:30Z\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|----------|\n| 409 | `CRM_FORM_VERSION_MISMATCH` | `updatedTime` does not match the current form version. Changes were not saved; the current version is in `error.currentUpdatedTime` |\n| 404 | `ENTITY_NOT_FOUND` | No form with this `id` |\n| 400 | `INVALID_PARAMS` | The body has no `updatedTime` |\n| 400 | `INVALID_PARAMS` | `id` is not a positive integer, the body is not a JSON object, the body formats are mixed, or a query string parameter was passed |\n| 402 | `CRM_FORM_WRITE_RESTRICTED` | The Bitrix24 plan (free or demo) does not allow writing CRM forms |\n| 403 | `CRM_FORM_SYSTEM_IMMUTABLE` | The form is a system form; its settings cannot be changed |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only. A key with write access is required |\n| 403 | `BITRIX_INSUFFICIENT_SCOPE` | The Bitrix24 token lacks the required scope |\n| 409 | `CRM_FORM_REST_NOT_ENABLED` | The CRM form methods are disabled on the Bitrix24 account |\n| 403 | `BITRIX_ACCESS_DENIED` | Bitrix24 denied access: the user has no permission to change CRM forms |\n| 403 | `SCOPE_DENIED` | The key lacks the `crm` scope |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` was not passed |\n| 401 | `TOKEN_MISSING` | The key has no Bitrix24 access tokens |\n| 422 | `BITRIX_ERROR` | Another Bitrix24 refusal. The original message is kept in `error.message` |\n| 500 | `CRM_FORM_SIDE_EFFECT_FAILED` | The changes are already written, but a subsequent step on the Bitrix24 side failed. Read the form before retrying |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a malformed response. The changes may have been saved — read the form before retrying |\n\nBitrix24 errors include the original code in `error.b24Code` and field violations in `error.validation` when provided. `CRM_FORM_*` codes retain their HTTP status, code and message. Common 429, 502 and 503 responses: [Limits and optimization](\u002Fdocs\u002Foptimization). Full list of common API errors: [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**Partial update.** Properties absent from the body stay unchanged. A passed array or object replaces the previous one entirely: to add one form field, pass all fields in `fields` together with the new one. An empty array clears the collection; `null` on a scalar property clears its value.\n\n## See also\n\n- [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget)\n- [Validate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fvalidate)\n- [Create a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fcreate)\n- [Activate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Factivate)\n- [Deactivate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fdeactivate)\n- [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields)\n- [Get the builder configuration](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n","## Delete a form\n\n`DELETE \u002Fv1\u002Fcrm-forms\u002F:id`\n\nDeletes a CRM form by ID together with its settings. A deleted form cannot be restored through the API — create a new one if needed.\n\n## Parameters\n\n| Parameter | Type | Required | Default | Description |\n|----------|-----|:-----:|-----------|----------|\n| `id` (path) | integer | yes | — | Form ID. List: [`GET \u002Fv1\u002Fcrm-forms`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist) |\n| `confirm` (query) | boolean | no | `false` | `true` confirms deletion of an active form. Without confirmation, an active form is not deleted — the response is `409 CRM_FORM_DELETE_CONFIRMATION_REQUIRED`. A deactivated form can be deleted without `confirm`. Accepts only `true` or `false` |\n| `confirmed` (query) | boolean | no | — | Alias of `confirm`. If both are supplied, their values must match, otherwise `400 INVALID_PARAMS` |\n| `updatedTime` (query) | string | no | — | Last modification time of the form from [`GET \u002Fv1\u002Fcrm-forms\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget). If the form was modified after this time, deletion is rejected with `409 CRM_FORM_VERSION_MISMATCH`. Without the parameter, no version check is performed |\n\nAny other query string parameter and any body field return `400 INVALID_PARAMS`. No request body is sent.\n\nBitrix24 validates the type and value of `updatedTime`. Use the version from the form read response; a local refusal for an invalid type is not guaranteed.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X DELETE \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75?confirm=true\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X DELETE \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75?confirm=true\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75?confirm=true', {\n  method: 'DELETE',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\nconst body = await res.json()\nif (body.success && body.data.deleted) {\n  console.log('Form deleted')\n}\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75?confirm=true', {\n  method: 'DELETE',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\nconst body = await res.json()\nif (body.success && body.data.deleted) {\n  console.log('Form deleted')\n}\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|----------|\n| `success` | boolean | `true` on successful deletion |\n| `data.deleted` | boolean | Always `true`: the form is deleted |\n\n## Response example\n\nHTTP status `200 OK`:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"deleted\": true\n  }\n}\n```\n\n## Error response example\n\n409 — the form is active and deletion was not confirmed:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CRM_FORM_DELETE_CONFIRMATION_REQUIRED\",\n    \"message\": \"The CRM form is active: confirm deletion and retry the request\",\n    \"b24Code\": \"CRM_FORM_DELETE_CONFIRMATION_REQUIRED\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|----------|\n| 400 | `INVALID_PARAMS` | `id` is not a positive integer, a query string parameter other than `confirm`, `confirmed` and `updatedTime` was passed, `confirm`, `confirmed` or `updatedTime` was repeated, the confirmation values conflict, `confirm` is neither `true` nor `false`, or a body field was passed |\n| 400 | `FST_ERR_CTP_EMPTY_JSON_BODY` | The `Content-Type: application\u002Fjson` header was passed with an empty body. Remove the header |\n| 402 | `CRM_FORM_WRITE_RESTRICTED` | The Bitrix24 plan does not allow writing CRM forms. Writes are not performed on free and demo plans |\n| 403 | `CRM_FORM_SYSTEM_IMMUTABLE` | The form is a system form — `system: true` in the [form list](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist). A system form cannot be deleted |\n| 404 | `ENTITY_NOT_FOUND` | No form with this `id`, including when the same form is deleted again |\n| 409 | `CRM_FORM_DELETE_CONFIRMATION_REQUIRED` | The form is active and deletion was not confirmed |\n| 409 | `CRM_FORM_VERSION_MISMATCH` | The form was modified after the passed `updatedTime`. The current modification time is in `error.currentUpdatedTime` |\n| 403 | `BITRIX_INSUFFICIENT_SCOPE` | The Bitrix24 token lacks the required scope |\n| 409 | `CRM_FORM_REST_NOT_ENABLED` | The CRM form methods are disabled on the Bitrix24 account |\n| 403 | `BITRIX_ACCESS_DENIED` | Bitrix24 denied access to the form for the key's user |\n| 422 | `BITRIX_ERROR` | Another Bitrix24 rejection. The rejection text is in `error.message` |\n| 500 | `CRM_FORM_SIDE_EFFECT_FAILED` | The deletion was performed but completed with an error. Check the form with [`GET \u002Fv1\u002Fcrm-forms\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) before retrying |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a response of an unexpected shape. Check the form before retrying |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only |\n| 403 | `SCOPE_DENIED` | The key lacks the `crm` scope |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is missing |\n| 401 | `TOKEN_MISSING` | The key has no valid Bitrix24 authorization |\n\nUpstream errors include the original code in `error.b24Code` and field violations in `error.validation` when provided. `CRM_FORM_*` codes retain their HTTP status, code and message. 429 and 503 responses are described in [Limits and optimization](\u002Fdocs\u002Foptimization). For the full list of common API errors, see [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n- **Deactivate instead of deleting.** To stop a form from working while keeping its settings, [deactivate](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fdeactivate) it — a deactivated form can be activated again.\n\n## See also\n\n- [Deactivate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fdeactivate)\n- [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget)\n- [List forms](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist)\n- [Create a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fcreate)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n","## Validate a form\n\n`POST \u002Fv1\u002Fcrm-forms\u002Fvalidate`\n\n`POST \u002Fv1\u002Fcrm-forms\u002F:id\u002Fvalidate`\n\nChecks a CRM form configuration without saving it and returns a list of violations. The first path checks a draft of a new form, the second checks changes to the saved form with the given ID.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|----------|\n| `id` (path) | integer | no | ID of a saved form — only for the `POST \u002Fv1\u002Fcrm-forms\u002F:id\u002Fvalidate` path. List: [`GET \u002Fv1\u002Fcrm-forms`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist) |\n\n## Request fields (body)\n\nPass either a flat body or an object in `fields`: `{\"fields\":{\"name\":\"Contact form\"}}`. An array in `fields` is the form field section of a flat body. Do not combine an object in `fields` with other top-level properties — this returns `400 INVALID_PARAMS`. Bitrix24 validates the form properties and values.\n\nThe body takes the same properties as form [creation](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fcreate) and [update](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fupdate). For a draft, pass the whole configuration. For a saved form, pass only the properties being changed, without `updatedTime`. An empty object `{}` checks the form as saved.\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|----------|\n| `name` | string \\| null | no | Form name. A draft without `name` gets a violation on this field |\n| `crm` | object | no | CRM binding. |\n| `crm.entityScheme` | integer | no | Scheme of the CRM records the form creates. List: `data.entitySchemes` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `active` | boolean | no | Whether the form is enabled. Bitrix24 validates whether this property is allowed |\n| `languageId` | string \\| null | no | Form language. List: `data.languages` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `templateId` | string \\| null | no | Scenario the form was created from. List: [List scenarios](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fscenarios) |\n| `appearance` | object | no | Appearance: `title`, `description`, button caption `buttonCaption` and other properties. |\n| `fields` | array \\| object | no | Form fields as an array, or a request envelope as an object |\n| `fields[].name` | string | no | Field name, for example `LEAD_NAME`. List: [`GET \u002Fv1\u002Fcrm-forms\u002Fentity-fields`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fentity-fields) |\n| `fields[].type` | string | no | Field type. List: `data.fieldTypes` in [`GET \u002Fv1\u002Fcrm-forms\u002Fconfiguration`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration) |\n| `fields[].label` | string | no | Field label in the form |\n| `fields[].required` | boolean | no | Whether the field is required for submission. Pass it explicitly: without the flag, `true` is set on save |\n| `fields[].multiple` | boolean | no | Whether the field accepts multiple values. Pass it explicitly: without the flag, `true` is set on save |\n| `responsible` | object | no | Users responsible for the form results |\n| `responsible.userIds` | array of integer | no | IDs of responsible users. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers) |\n| `agreements` | object | no | Agreement settings in the Bitrix24 schema |\n| `submission` | object | no | Post-submission settings. |\n| `callback` | object | no | Callback settings. |\n| `payment` | object | no | Payment settings. |\n| `booking` | object | no | Booking settings. |\n| `presetFields` | array | no | Preset field values |\n| `dependencies` | array | no | Dependencies between fields |\n| `analytics` | object | no | Analytics settings |\n| `integrations` | object | no | Integration settings |\n| `spamProtection` | object | no | Spam protection settings |\n\nThe [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields) reference describes top-level metadata only. For a saved form, take nested property names and the current section values from the full [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) response. Sections are passed in the Bitrix24 schema; Bitrix24 decides which settings can be written.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002Fvalidate\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"name\": \"Feedback form\",\n    \"crm\": { \"entityScheme\": 1 },\n    \"fields\": [\n      { \"name\": \"LEAD_NAME\", \"type\": \"string\", \"label\": \"Name\", \"required\": false, \"multiple\": false },\n      { \"name\": \"LEAD_PHONE\", \"type\": \"phone\", \"label\": \"Phone\", \"required\": false, \"multiple\": false }\n    ]\n  }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002Fvalidate\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"name\": \"Feedback form\",\n    \"crm\": { \"entityScheme\": 1 },\n    \"fields\": [\n      { \"name\": \"LEAD_NAME\", \"type\": \"string\", \"label\": \"Name\", \"required\": false, \"multiple\": false },\n      { \"name\": \"LEAD_PHONE\", \"type\": \"phone\", \"label\": \"Phone\", \"required\": false, \"multiple\": false }\n    ]\n  }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002Fvalidate', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    name: 'Feedback form',\n    crm: { entityScheme: 1 },\n    fields: [\n      { name: 'LEAD_NAME', type: 'string', label: 'Name', required: false, multiple: false },\n      { name: 'LEAD_PHONE', type: 'phone', label: 'Phone', required: false, multiple: false },\n    ],\n  }),\n})\n\nconst { data } = await res.json()\nif (!data.valid) console.log('Violations:', data.violations)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002Fvalidate', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    name: 'Feedback form',\n    crm: { entityScheme: 1 },\n    fields: [\n      { name: 'LEAD_NAME', type: 'string', label: 'Name', required: false, multiple: false },\n      { name: 'LEAD_PHONE', type: 'phone', label: 'Phone', required: false, multiple: false },\n    ],\n  }),\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nHTTP `200` on both paths, including when the check fails.\n\n| Field | Type | Description |\n|------|-----|----------|\n| `success` | boolean | `true` — the check was performed. The check result is in `data.valid` |\n| `data.valid` | boolean | `true` — no violations, `false` — the configuration needs fixing |\n| `data.violations` | array | Violations. An empty array when `valid: true` |\n| `data.violations[].field` | string | Path to the property with the violation, for example `name` |\n| `data.violations[].message` | string | Violation text |\n| `meta.redacted` | array of string | JSON paths where the current connection's credentials were replaced |\n\n## Response example\n\nNo violations:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"valid\": true,\n    \"violations\": []\n  }\n}\n```\n\nThe check failed — the draft has no `name`:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"valid\": false,\n    \"violations\": [\n      {\n        \"field\": \"name\",\n        \"message\": \"Name of the CRM form is required\"\n      }\n    ]\n  }\n}\n```\n\n## Error response example\n\n400 — an object in `fields` is combined with another top-level property:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"INVALID_PARAMS\",\n    \"message\": \"Use either a flat body or {fields:{...}}\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|----------|\n| 404 | `ENTITY_NOT_FOUND` | Bitrix24 did not find a requested entity or field descriptor. The original code is in `error.b24Code` |\n| 400 | `INVALID_PARAMS` | `id` is not a positive integer, the body is not a JSON object, or a query string parameter was passed |\n| 403 | `CRM_FORM_SYSTEM_IMMUTABLE` | Path with `id` only: the form is a system form; its settings cannot be changed |\n| 403 | `BITRIX_INSUFFICIENT_SCOPE` | The Bitrix24 token lacks the required scope |\n| 409 | `CRM_FORM_REST_NOT_ENABLED` | The CRM form methods are disabled on the Bitrix24 account |\n| 403 | `BITRIX_ACCESS_DENIED` | Bitrix24 denied access: the user has no permission to change CRM forms |\n| 403 | `SCOPE_DENIED` | The key lacks the `crm` scope |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` was not passed |\n| 401 | `TOKEN_MISSING` | The key has no Bitrix24 access tokens |\n| 422 | `BITRIX_ERROR` | Any other Bitrix24 refusal. The original message is kept in `error.message` |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a malformed response |\n\nBitrix24 errors include the original code in `error.b24Code` and field violations in `error.validation` when provided. `CRM_FORM_*` codes retain their HTTP status, code and message. Common 429, 502 and 503 responses: [Limits and optimization](\u002Fdocs\u002Foptimization). Full list of common API errors: [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**Works with a read-only key.** The check saves nothing and does not change the form's `updatedTime`, so a read-only key can call it too.\n\n## See also\n\n- [Create a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fcreate)\n- [Update a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fupdate)\n- [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget)\n- [Form contract fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Ffields)\n- [Get the builder configuration](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration)\n- [List entity fields](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fentity-fields)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n","## Activate a form\n\n`POST \u002Fv1\u002Fcrm-forms\u002F:id\u002Factivate`\n\nActivates a CRM form by ID after checking its configuration and the account's active-form limit.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|----------|\n| `id` (path) | integer | yes | Form ID. List: [`GET \u002Fv1\u002Fcrm-forms`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist) |\n\nThe method takes no query string parameters: any such parameter returns `400 INVALID_PARAMS`.\n\n## Request fields (body)\n\nThe body can be omitted or passed as an empty object `{}`. Any field other than `updatedTime` returns `400 INVALID_PARAMS`.\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|----------|\n| `updatedTime` | string | no | Last modification time of the form from [`GET \u002Fv1\u002Fcrm-forms\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget). If the form was modified after this time, activation is rejected with `409 CRM_FORM_VERSION_MISMATCH`. Without the field, no version check is performed |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75\u002Factivate\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{}'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75\u002Factivate\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{}'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75\u002Factivate', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({}),\n})\nconst { data } = await res.json()\nconsole.log(data.active, data.updatedTime)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75\u002Factivate', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({}),\n})\nconst { data } = await res.json()\nconsole.log(data.active, data.updatedTime)\n```\n\nBitrix24 validates the type and value of `updatedTime`.\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|----------|\n| `success` | boolean | `true` on successful activation |\n| `data.active` | boolean | Form state after the call |\n| `data.updatedTime` | string | Last modification time of the form after activation, ISO 8601 with a time zone offset. Pass it in the next write request |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"active\": true,\n    \"updatedTime\": \"2026-11-05T08:25:33Z\"\n  }\n}\n```\n\n## Error response example\n\n409 — the form was modified after the time passed in `updatedTime`:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CRM_FORM_VERSION_MISMATCH\",\n    \"message\": \"The CRM form version is outdated. Changes were not saved. Get the form again and retry the request\",\n    \"b24Code\": \"CRM_FORM_VERSION_MISMATCH\",\n    \"currentUpdatedTime\": \"2026-11-05T08:25:30Z\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|----------|\n| 400 | `INVALID_PARAMS` | `id` is not a positive integer, a query string parameter is passed, the body is not a JSON object, or the body contains a field other than `updatedTime` |\n| 402 | `CRM_FORM_ACTIVATION_LIMIT_REACHED` | The account's active-form limit has been reached |\n| 402 | `CRM_FORM_WRITE_RESTRICTED` | The Bitrix24 plan does not allow writing CRM forms. Writes are not performed on free and demo plans |\n| 403 | `CRM_FORM_SYSTEM_IMMUTABLE` | The form is a system form — `system: true` in the [form list](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist) |\n| 404 | `ENTITY_NOT_FOUND` | No form with this `id` |\n| 409 | `CRM_FORM_VERSION_MISMATCH` | The form was modified after the passed `updatedTime`. The current modification time is in `error.currentUpdatedTime` |\n| 403 | `BITRIX_INSUFFICIENT_SCOPE` | The Bitrix24 token lacks the required scope |\n| 409 | `CRM_FORM_REST_NOT_ENABLED` | The CRM form methods are disabled on the Bitrix24 account |\n| 403 | `BITRIX_ACCESS_DENIED` | Bitrix24 denied access to the form for the key's user |\n| 422 | `BITRIX_ERROR` | Any other Bitrix24 refusal. The refusal text is in `error.message` |\n| 500 | `CRM_FORM_SIDE_EFFECT_FAILED` | The change is already saved, but the operation completed with an error. Re-read the form via [`GET \u002Fv1\u002Fcrm-forms\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) before retrying |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a response of an unexpected shape. Re-read the form before retrying |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only |\n| 403 | `SCOPE_DENIED` | The key lacks the `crm` scope |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not passed |\n| 401 | `TOKEN_MISSING` | The key has no valid Bitrix24 authorization |\n\nBitrix24 errors include the original code in `error.b24Code` and field violations in `error.validation` when provided. `CRM_FORM_*` codes retain their HTTP status, code and message. 429 and 503 responses are described in [Limits and optimization](\u002Fdocs\u002Foptimization). For the full list of common API errors, see [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n- **The active-form limit can be checked in advance.** The account's current number of active forms is `limits.activeForms.current`, and the ceiling is `limits.activeForms.maximum` in the [builder configuration](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration). When the ceiling is reached, free up a slot by [deactivating](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fdeactivate) another form.\n- **A repeated call does not return an error.** Activating an already active form returns `200` with `active: true`, and `updatedTime` does not change.\n\n## See also\n\n- [Deactivate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fdeactivate)\n- [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget)\n- [Form list](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist)\n- [Get builder configuration](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fconfiguration)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n","## Deactivate a form\n\n`POST \u002Fv1\u002Fcrm-forms\u002F:id\u002Fdeactivate`\n\nDeactivates a CRM form by ID and keeps its settings, so a deactivated form can be activated again.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|----------|\n| `id` (path) | integer | yes | Form ID. List: [`GET \u002Fv1\u002Fcrm-forms`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist) |\n\nThe method takes no query string parameters: any such parameter returns `400 INVALID_PARAMS`.\n\n## Request fields (body)\n\nThe body can be omitted or passed as an empty object `{}`. Any field other than `updatedTime` returns `400 INVALID_PARAMS`.\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|----------|\n| `updatedTime` | string | no | Last modification time of the form from [`GET \u002Fv1\u002Fcrm-forms\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget). If the form was modified after this time, deactivation is rejected with `409 CRM_FORM_VERSION_MISMATCH`. Without the field, no version check is performed |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75\u002Fdeactivate\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{}'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75\u002Fdeactivate\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{}'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75\u002Fdeactivate', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({}),\n})\nconst { data } = await res.json()\nconsole.log(data.active, data.updatedTime)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-forms\u002F75\u002Fdeactivate', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({}),\n})\nconst { data } = await res.json()\nconsole.log(data.active, data.updatedTime)\n```\n\nBitrix24 validates the type and value of `updatedTime`.\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|----------|\n| `success` | boolean | `true` on successful deactivation |\n| `data.active` | boolean | Form state after the call |\n| `data.updatedTime` | string | Last modification time of the form after deactivation, ISO 8601 with a time zone offset. Pass it in the next write request |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"active\": false,\n    \"updatedTime\": \"2026-11-05T08:25:34Z\"\n  }\n}\n```\n\n## Error response example\n\n404 — no form with this `id`:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"b24Code\": \"BITRIX_REST_V3_EXCEPTION_ENTITYNOTFOUNDEXCEPTION\",\n    \"message\": \"Record with ID = `99999999` not found\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|----------|\n| 400 | `INVALID_PARAMS` | `id` is not a positive integer, a query string parameter is passed, the body is not a JSON object, or the body contains a field other than `updatedTime` |\n| 402 | `CRM_FORM_WRITE_RESTRICTED` | The Bitrix24 plan does not allow writing CRM forms. Writes are not performed on free and demo plans |\n| 403 | `CRM_FORM_SYSTEM_IMMUTABLE` | The form is a system form — `system: true` in the [form list](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist). A system form cannot be deactivated |\n| 404 | `ENTITY_NOT_FOUND` | No form with this `id` |\n| 409 | `CRM_FORM_VERSION_MISMATCH` | The form was modified after the passed `updatedTime`. The current modification time is in `error.currentUpdatedTime` |\n| 403 | `BITRIX_INSUFFICIENT_SCOPE` | The Bitrix24 token lacks the required scope |\n| 409 | `CRM_FORM_REST_NOT_ENABLED` | The CRM form methods are disabled on the Bitrix24 account |\n| 403 | `BITRIX_ACCESS_DENIED` | Bitrix24 denied the key's user access to the form |\n| 422 | `BITRIX_ERROR` | Another Bitrix24 refusal. The refusal text is in `error.message` |\n| 500 | `CRM_FORM_SIDE_EFFECT_FAILED` | The change is already saved, but the operation completed with an error. Re-read the form via [`GET \u002Fv1\u002Fcrm-forms\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget) before retrying |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a response of an unexpected shape. Re-read the form before retrying |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only |\n| 403 | `SCOPE_DENIED` | The key lacks the `crm` scope |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not passed |\n| 401 | `TOKEN_MISSING` | The key has no valid Bitrix24 authorization |\n\nUpstream errors include the original code in `error.b24Code` and field violations in `error.validation` when provided. `CRM_FORM_*` codes retain their HTTP status, code and message. 429 and 503 responses are described in [Limits and optimization](\u002Fdocs\u002Foptimization). Full list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n- **A repeated call does not return an error.** Deactivating an already inactive form returns `200` with `active: false`, and `updatedTime` does not change.\n\n## See also\n\n- [Activate a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Factivate)\n- [Delete a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fdelete)\n- [Get a form](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Fget)\n- [Form list](\u002Fdocs\u002Fentities\u002Fcrm-forms\u002Flist)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n",1794739355157]