# Send a CRM form to a customer

`POST /v1/openlines/sessions/send-form`

Sends a CRM form into an Open Channel dialog. The customer receives a real message. Bitrix24 checks the current user's access to the chat.

Requires both `imopenlines` and `crm` scopes and a key with write access.

## Request fields (body)

| Field | Type | Req. | Description |
|---|---|---|---|
| `sessionId` | integer | yes | Positive Open Channel session ID, not a `chatId`. Search: [`POST /v1/openlines/sessions/search`](/docs/openlines/sessions/search) |
| `formId` | integer | yes | Positive CRM form ID. List: [`GET /v1/crm-forms`](/docs/entities/crm-forms/list) |

Only these two fields are accepted. The server resolves the form code, name and public security code. Retrieving this metadata may generate missing JavaScript loaders for forms in Bitrix24.

## Examples

### curl — personal key

```bash
curl -X POST 'https://vibecode.bitrix24.com/v1/openlines/sessions/send-form' \
  -H 'X-Api-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"sessionId":9,"formId":8}'
```

### curl — OAuth application

```bash
curl -X POST 'https://vibecode.bitrix24.com/v1/openlines/sessions/send-form' \
  -H 'X-Api-Key: YOUR_APP_KEY' \
  -H 'Authorization: Bearer USER_SESSION_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"sessionId":9,"formId":8}'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/openlines/sessions/send-form', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ sessionId: 9, formId: 8 }),
})
const { data } = await res.json()
console.log(data.sent)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/openlines/sessions/send-form', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ sessionId: 9, formId: 8 }),
})
const { data } = await res.json()
console.log(data.sent)
```

## Response fields

| Field | Type | Description |
|---|---|---|
| `success` | boolean | Always `true` on success |
| `data.sent` | boolean | Always `true`: Bitrix24 accepted the send call |

## Response example

```json
{
  "success": true,
  "data": {
    "sent": true
  }
}
```

## Error response example

404 — session not found:

```json
{
  "success": false,
  "error": {
    "code": "NO_SESSION_ERROR",
    "message": "Error getting session info"
  }
}
```

## Errors

| HTTP | Code | Description |
|---|---|---|
| 400 | `MISSING_REQUIRED_FIELDS` | `sessionId` or `formId` is missing |
| 400 | `INVALID_PARAMS` | The body is not a JSON object, a field other than `sessionId` and `formId` was passed, or an ID is not a positive integer |
| 400 | `SESSION_ID_EMPTY` | Bitrix24 rejected the request: the session ID was not passed |
| 400 | `FORM_INFO_EMPTY` | Bitrix24 rejected the request: the form data is missing |
| 403 | `SCOPE_DENIED` | The key lacks the `imopenlines` or `crm` scope |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only |
| 403 | `ACCESS_ERROR` | Bitrix24 denied access to the dialog |
| 404 | `NO_SESSION_ERROR` | No session with this `sessionId` |
| 404 | `ENTITY_NOT_FOUND` | No form with this `formId` in the Bitrix24 account. The message text comes from Bitrix24 |
| 404 | `ENTITY_NOT_FOUND` | The form exists but is missing from the account's form list. The message is `CRM form not found` |
| 502 | `BITRIX_RESPONSE_INVALID` | Bitrix24 returned invalid form data or did not confirm the send |

Bitrix24 refusal messages are passed through unchanged. For common refusals, see [Limits and optimization](/docs/optimization). For the full list of common API errors, see [Errors](/docs/errors).

## Known specifics

**`sent` does not confirm delivery.** The field means Bitrix24 accepted the call, not that the customer received the message. Internal form codes are not returned.

**A retry after a failure may send a duplicate.** If no response arrived or the response was `502 BITRIX_RESPONSE_INVALID`, the form may already have reached the customer. Check the dialog before retrying, or the customer will receive the form twice.

## See also

- [Session search](/docs/openlines/sessions/search)
- [List forms](/docs/entities/crm-forms/list)
- [Submit visitor data](/docs/entities/crm-forms/results)
- [Limits and optimization](/docs/optimization)
