# Bitrix24 (inbound webhook) Create leads and read deals in Bitrix24. URL: https://docs.qaldy.com/connectors/bitrix24/ - **Status:** [[Available]] - **Shelf:** CRM - **How you connect:** Webhook URL - **Regions:** global and Kazakhstan - **The service’s own API reference:** https://apidocs.bitrix24.com/ Apps create leads and read deals in your Bitrix24 through an **inbound webhook**. The webhook URL is the credential: `https://.bitrix24./rest///`. Qaldy seals `/` to the gate and the gate puts it into the URL path (`path_token` auth), so the app never sees it. > **Status: Available through the HTTP API preset.** The preset follows Bitrix24's REST webhook > documentation (checked 2026-10-16). It has not been run against a live portal. ## Connect it 1. In Bitrix24 open **Developer resources → Other → Inbound webhook** ([apidocs.bitrix24.com](https://apidocs.bitrix24.com/)). 2. Tick **only the permissions the apps need** (for leads and deals: `crm`). The webhook's scopes are the real fence on what an app can do; the gate's host and path fence is the second. 3. Copy the webhook URL. 4. Qaldy → **Connectors** → Bitrix24 → **Connect Bitrix24** → paste the **whole URL** → **Seal and connect**. Qaldy reads your portal (`acme.bitrix24.kz`) and the secret (`1/abcdefghijklmnop`) from it; anything after the secret (a method name) is dropped. Only the secret is sealed, and it is never shown again. **Test connection** calls `GET /rest//profile.json`, which answers for any valid webhook. ## What the gate allows | | | |---|---| | Host | your portal, as pasted (`.bitrix24.`), base path `/rest` (pinned, every resolved address public; IP literals and private names are refused) | | Methods | `GET`, `POST` | | Paths | the REST method the app names (`/crm.lead.add.json`, `/crm.deal.list.json`) | | Secret | spliced into the path by the gate: `/rest///`; the app can't read, replace or climb out of it | ## Use it from an app ```json { "id": "http", "actions": ["request"], "scope": "conn_k3v9…" } ``` ```ts const api = ctx.connectors.http('conn_k3v9…') await api.post('/crm.lead.add.json', { json: { fields: { TITLE: 'Website lead', NAME: 'Aigerim' } } }) const deals = await api.post('/crm.deal.list.json', { json: { filter: { STAGE_ID: 'NEW' } } }) ``` Bitrix24 puts the reason in an `error` field (with an `error_description`) of the reply; the connector throws it as an `upstream_error` carrying that message. With `throwOnError: false`, read `res.body.error` yourself. ## When it breaks | You see | Why | Do | |---|---|---| | `error: "INVALID_CREDENTIALS"` or `401` | The webhook was deleted or the code mistyped | Create a new webhook and replace the secret | | `error: "insufficient_scope"` | The webhook lacks a permission | Edit its permissions in Bitrix24 | | Setup says "The address is missing its secret part" | The pasted URL has no `/` | Copy the whole URL from Inbound webhook |