Integration of 1C-Bitrix with amoCRM
Orders in Bitrix, leads in amoCRM, managers switch between two tabs and manually copy data. Client contact in CRM doesn't match order data, conversation history is broken. Integration eliminates manual labor and builds a unified funnel: from first site visit to deal closure. Let's examine the architecture, amoCRM API, typical data flows, and pitfalls.
Data Flows
| Flow | Direction | Trigger | Priority |
|---|---|---|---|
| Leads from site forms | Bitrix → amoCRM | Form submission | High |
| Orders | Bitrix → amoCRM | Order checkout | Critical |
| Contacts | Bitrix ↔ amoCRM | On lead/order creation | High |
| Deal statuses | amoCRM → Bitrix | Pipeline stage change | Medium |
| Catalog products | Bitrix → amoCRM | By schedule | Low |
Main flow — orders and leads from Bitrix to amoCRM. Reverse flow (statuses) is needed if site has personal account with order processing tracking.
amoCRM API v4
amoCRM uses OAuth 2.0 with long-lived refresh token. After authorization via integration (Settings → Integrations in amoCRM), you receive client_id, client_secret, redirect_uri. Initial code-to-token exchange — standard OAuth flow. Refresh token updates on each token refresh (access token lifetime — 20 minutes).
Token Storage in Bitrix: b_option table of module or separate table. Mandatory to encrypt or store outside public directory. Cache access token in runtime, refresh only on 401.
Base API URL: https://{subdomain}.amocrm.ru/api/v4/.
Key endpoints:
-
POST /leads— deal creation. -
POST /contacts— contact creation. -
POST /leads/complex— deal creation with contact and company in one request. Recommended method — atomic operation. -
GET /leads/{id}— get deal. -
PATCH /leads/{id}— update deal (status change, field addition). -
POST /catalogs/{catalog_id}/elements— products in amoCRM catalog.
Limitations: 7 requests per second per account. Exceeding returns HTTP 429 with Retry-After header.
Deal Creation on Order Checkout
Event handler OnSaleOrderSaved (module sale):
use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler(
'sale', 'OnSaleOrderSaved',
['AmoCrmIntegration', 'onOrderSaved']
);
Method onOrderSaved extracts order data and forms request to amoCRM:
-
Contact Search —
GET /contacts?query={phone_or_email}. If found — use its ID. If not — create new. -
Deal Creation —
POST /leads/complexwith contact binding, name "Order #{ORDER_ID}", amount, UTM-tags in custom fields.
Order field mapping Bitrix → amoCRM:
| Bitrix (order) | amoCRM (deal) | Field Type |
|---|---|---|
PRICE (order amount) |
price |
Standard |
STATUS_ID |
status_id (pipeline stage) |
Standard |
| Buyer first name + last name | contacts[0].first_name/last_name |
Contact |
| Phone | contacts[0].custom_fields (PHONE) |
Contact |
contacts[0].custom_fields (EMAIL) |
Contact | |
| Product list | Note or amoCRM catalog | Custom |
| UTM-tags (from cookie/properties) | Deal custom fields | Custom |
UTM-tags — separate task. Bitrix out of box doesn't save UTM in order. Need to catch them on front (JavaScript), save in cookie or $_SESSION, and on order checkout write to properties (PROPERTY_UTM_SOURCE, PROPERTY_UTM_MEDIUM, etc.). From there — to deal custom fields in amoCRM.
Status Synchronization Back
amoCRM supports webhooks — on pipeline stage change, sends POST to specified URL. Create handler /local/tools/amocrm_webhook.php:
- Accept POST from amoCRM (array
leads[status][0]). - Extract deal
idandstatus_id(pipeline stage ID). - Find Bitrix order by deal
id(via order custom fieldPROPERTY_AMO_LEAD_IDor mapping table). - Update order status via
\Bitrix\Sale\Order::load($orderId)→setField('STATUS_ID', $mappedStatus)→save().
Mapping of amoCRM funnel statuses → Bitrix order statuses stored in config: array [amo_status_id => bitrix_status_id].
Webhook Security: amoCRM doesn't sign requests. Verify sender IP (amoCRM IP list in docs) or use secret parameter in URL.
Site Form Processing
Feedback forms, callback, questions — all are leads. Two approaches:
-
Via Bitrix Web Forms — handler
OnAfterResultAdd(moduleform) orOnAfterFormResultAddcreates deal in amoCRM. - Via amoCRM Forms — amoCRM JS-widget on site, data goes directly to CRM, bypassing Bitrix. Simpler but loses Bitrix connection.
Recommendation — first option. Data first saved in Bitrix (reliable storage), then async sent to amoCRM.
Queue and Error Handling
amoCRM API may be unavailable (HTTP 500, 429, network error). Put order/lead sending in queue:
- Table
amocrm_queuewith fieldsid,type(lead/order/status),payload(JSON),attempts,status,last_error,created_at. - Agent or cron-script processes queue every minute. On error — increment
attempts, ifattempts > 5—status = 'failed', notify.
Timelines
| Stage | Time |
|---|---|
| OAuth-integration + token storage | 1 day |
| Order transmission → deals | 2-3 days |
| Contacts: duplicate search + creation | 1-2 days |
| UTM-tags: collection + transmission | 1 day |
| Webhook reverse status sync | 1-2 days |
| Forms → leads | 1 day |
| Queue + error handling | 1 day |
| Testing, edge cases | 1-2 days |
| Total | 1-2 weeks |







