Reactive CRM Руководство по интеграции ← Назад на сайт

Руководство по интеграции ReactiveCRM

Техническая документация для компаний (тенантов), которые хотят построить собственную интеграцию с ReactiveCRM: приём лидов и клиентов, создание сделок, отправка маркетинговых событий и экспорт данных.

Этот документ охватывает только API, наиболее часто используемые для внешних интеграций. Внутренние справочные данные и эндпоинты админ-сервисов намеренно вынесены за рамки.

1. Обзор интеграции

Типичный сценарий интеграции выглядит так:

text
Your system (backend / server-side proxy)
    |
    | 1. POST /api/auth/login  (obtain access + refresh tokens)
    v
ReactiveCRM
    | 2. References: GET /api/users/paged, GET /api/statuses, GET /api/stages, GET /api/lead-sources
    |    (obtain UUIDs for ownerId, authorId, statusId, etc.)
    v
    | 3. Core operations:
    |      POST /api/leads/create              — create a lead
    |      POST /api/clients/create            — create a client
    |      POST /api/contacts/create           — create a contact
    |      POST /api/deals/create              — create a deal
    |      POST /api/dashboard/marketing/events — send a marketing event
    |      POST /api/leads/import/batch         — bulk import leads
    v
    | 4. Read / export:
    |      GET /api/leads/paged                 — paged read with filters
    |      GET /api/export/leads                — NDJSON export of all leads

Ключевое правило безопасности: никогда не вызывайте CRM API напрямую из браузера конечного пользователя. Храните CRM-токен и внутренние идентификаторы на своём бэкенде (или в serverless-функции).

2. Аутентификация

2.1. Получение токенов

Эндпоинты аутентификации не требуют токена:

МетодURLОписание
POST/api/auth/loginВход по логину и паролю, возвращает access- и refresh-токены
POST/api/auth/refreshОбмен refresh-токена на новую пару токенов
POST/api/auth/logoutОтзыв refresh-токена
bash
curl -X POST "$CRM_BASE_URL/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"username": "integration", "password": "secret123"}'
json
{
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "refreshToken": "a8f3k2m9Qx7Tt1Vv...",
  "tokenType": "Bearer",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "firstName": "Integration",
    "lastName": "Bot",
    "tenantId": "660e8400-e29b-41d4-a716-446655440001"
  },
  "tenant": {
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "name": "Zunga Corp"
  }
}

2.2. Правила работы с токенами

2.3. Базовые настройки

text
CRM_BASE_URL=https://crm.example.com

Во всех примерах ниже подразумеваются заголовки:

http
Authorization: Bearer <CRM_ACCESS_TOKEN>
Content-Type: application/json

3. Соглашения постраничного API

Все списочные эндпоинты вида GET /api/*/paged используют одинаковые соглашения:

ПараметрТипПо умолчаниюОписание
pageinteger0Номер страницы, с нуля
sizeintegerзависит от эндпоинтаРазмер страницы
sortstringcreatedAt,descСортировка в формате field,direction. Направление: asc или desc

Формат постраничного ответа

json
{
  "content": [ { "..." } ],
  "page": 0,
  "size": 20,
  "totalElements": 137,
  "totalPages": 7
}

Фильтрация по дате

Используйте параметры fieldFrom / fieldTo для диапазонов (ISO 8601):

text
createdAtFrom=2026-01-01T00:00:00Z
createdAtTo=2026-01-31T23:59:59Z

Сортировка

Всегда ?sort=field,direction:

text
?sort=createdAt,desc
?sort=name,asc

Некоторые поля фильтрации имеют отдельные параметры диапазона (например, dealAmountFrom/dealAmountTo).

Семантика фильтрации

4. Справочники (получение UUID)

Перед созданием сущностей получите UUID связанных справочных данных. Основные:

4.1. Пользователи (GET /api/users/paged)

Используется для ownerId, authorId, developingManagerIds.

bash
curl "$CRM_BASE_URL/api/users/paged?page=0&size=50&sort=createdAt,asc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

Пример ответа (фрагмент content):

json
[
  {
    "id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "firstName": "Roman",
    "lastName": "Posledovskiy",
    "username": "roman",
    "email": "roman@example.com",
    "tenantId": "660e8400-e29b-41d4-a716-446655440001"
  }
]

4.2. Статусы (GET /api/statuses)

Используется для statusId лидов, сделок и клиентов-сторон сделки. Возвращает массив:

bash
curl "$CRM_BASE_URL/api/statuses" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"
json
[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "New",
    "entityType": "LEAD"
  },
  {
    "id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
    "name": "In progress",
    "entityType": "STAGE"
  }
]

4.3. Стадии (GET /api/stages)

Используется для stageId сделки:

bash
curl "$CRM_BASE_URL/api/stages" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

4.4. Источники лидов (GET /api/lead-sources)

Возвращает дерево источников лидов. Используется для leadSourceId лида:

bash
curl "$CRM_BASE_URL/api/lead-sources" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"
json
[
  {
    "id": "cccc0001-0000-0000-0000-000000000001",
    "name": "Website",
    "children": [
      {
        "id": "cccc0001-0000-0000-0000-000000000002",
        "name": "Feedback form",
        "children": []
      }
    ]
  }
]

5. Лиды

5.1. Создание лида (POST /api/leads/create)

bash
curl -X POST "$CRM_BASE_URL/api/leads/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Website inquiry: consultation",
    "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "leadSourceId": "cccc0001-0000-0000-0000-000000000002",
    "statusId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "quality": "WARM"
  }'

Поля запроса:

ПолеТипОбязательноОписание
messagestringнетТекст сообщения / обращения
ownerIduuidдаОтветственный пользователь
authorIduuidдаПользователь, создавший лид
clientIduuidнетСвязанный клиент
contactIduuidнетСвязанный контакт
leadSourceIduuidнетУзел дерева источников лидов
statusIduuidнетСтатус
qualityenumнетHOT, WARM, COOL, COLD

Пример ответа 201 Created:

json
{
  "id": "22222222-2222-2222-2222-222222222222",
  "message": "Website inquiry: consultation",
  "status": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "New"
  },
  "quality": "WARM",
  "dealId": null,
  "createdAt": "2026-09-05T20:00:00Z",
  "updatedAt": "2026-09-05T20:00:00Z",
  "version": 0,
  "author": {
    "id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "firstName": "Roman",
    "lastName": "Posledovskiy"
  },
  "owner": {
    "id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "firstName": "Roman",
    "lastName": "Posledovskiy"
  }
}

Сохраните возвращённый id — он нужен для leadId маркетингового события (см. раздел 8).

5.2. Постраничное чтение (GET /api/leads/paged)

bash
curl "$CRM_BASE_URL/api/leads/paged?page=0&size=20&createdAtFrom=2026-09-01T00:00:00Z&sort=createdAt,desc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

Основные фильтры:

ПараметрТипРежимОписание
statusIduuidточноеФильтр по статусу
leadSourceIduuidточноеФильтр по источнику лида
qualityenumточноеHOT, WARM, COOL, COLD
messagestringILIKEПодстрока в сообщении
searchstringILIKE (OR)Поиск по сообщению, контакту, email, телефону
contactEmailstringILIKEПо email контакта
contactPhonestringILIKEПо телефону контакта
companystringILIKEПо названию компании
clientIduuidточноеПо ID клиента
createdAtFrom / createdAtTodate-timeдиапазонПо дате создания
updatedAtFrom / updatedAtTodate-timeдиапазонПо дате обновления
createdByuuidточноеПо автору лида

Также есть фильтры по связанной сделке: dealStatusId, dealStageId, dealAmountFrom/dealAmountTo, dealProbabilityFrom/dealProbabilityTo.

Сортировка: createdAt, updatedAt, message, quality, статус/источник и другие (формат field,direction).

5.3. Получение одного лида (GET /api/leads/{id})

bash
curl "$CRM_BASE_URL/api/leads/$LEAD_ID" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

5.4. Массовый импорт лидов (POST /api/leads/import/batch)

Для массового приёма большого числа лидов используйте batch-эндпоинт. Он принимает массив лидов, создаёт запись в истории импорта и позволяет откатить весь импорт.

bash
curl -X POST "$CRM_BASE_URL/api/leads/import/batch" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileName": "leads-2026-09-05.csv",
    "leads": [
      {
        "message": "Inquiry #1",
        "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
        "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
        "quality": "WARM"
      },
      {
        "message": "Inquiry #2",
        "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
        "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
        "quality": "COOL"
      }
    ]
  }'

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

json
{
  "importId": "44444444-4444-4444-4444-444444444444",
  "imported": 2,
  "total": 2,
  "skipped": []
}

История и откат:

bash
# История импорта
curl "$CRM_BASE_URL/api/leads/import/history" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

# Откат импорта
curl -X POST "$CRM_BASE_URL/api/leads/import/rollback/$IMPORT_ID" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

5.5. Быстрый лид с сайта (POST /api/site/leads)

Для форм на сайте есть единый комбинированный эндпоинт, который атомарно создаёт контакт, его основной телефон и email, лид, связь «контакт–лид» и маркетинговое событие в одном запросе — с идемпотентностью через externalId.

См. отдельное руководство: site-lead-multi-contract.md.

6. Клиенты и контакты

6.1. Создание клиента (POST /api/clients/create)

bash
curl -X POST "$CRM_BASE_URL/api/clients/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "COMPANY",
    "name": "Romashka LLC",
    "taxId": "7700000001",
    "regNumber": "1234567890",
    "country": "RU",
    "phone": "+7-495-000-00-01",
    "email": "info@romashka.ru",
    "website": "https://romashka.ru",
    "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
  }'

Основные поля:

ПолеТипПрименяется кОписание
typeenumвсеINDIVIDUAL или COMPANY (обязательно)
namestringвсеОтображаемое имя (обязательно)
firstName / lastNamestringINDIVIDUALИмя/фамилия
taxIdstringCOMPANYИНН
regNumberstringCOMPANYРегистрационный номер
legalAddressstringCOMPANYЮридический адрес
phone / email / websitestringвсеКонтакты
countrystringвсеКод страны по ISO
ownerIduuidвсеОтветственный пользователь
authorIduuidвсеАвтор
developingManagerIdsuuid[]всеРазвивающие менеджеры

6.2. Постраничное чтение клиентов (GET /api/clients/paged)

bash
curl "$CRM_BASE_URL/api/clients/paged?page=0&size=20&type=COMPANY&search=Romashka&sort=name,asc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

Основные фильтры: name, type (INDIVIDUAL/COMPANY), country, taxId, email, phone, lastName (для физлиц), search (по имени/ИНН/телефону), createdAtFrom/createdAtTo, createdBy, developingManagerId.

6.3. Проверка дубликатов (GET /api/clients/duplicates)

Перед созданием клиента проверьте, не существует ли похожий:

bash
# По ИНН и названию
curl "$CRM_BASE_URL/api/clients/duplicates?type=COMPANY&taxId=7700000001&name=Romashka" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

6.4. Создание контакта (POST /api/contacts/create)

bash
curl -X POST "$CRM_BASE_URL/api/contacts/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Ivan",
    "lastName": "Petrov",
    "dateOfBirth": "1990-05-15",
    "gender": "MALE",
    "countryCode": "RU",
    "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
  }'

Поля: firstName (обязательно), lastName, patronymicName, dateOfBirth (date), gender (MALE/FEMALE), countryCode, ownerId, authorId.

6.5. Постраничное чтение контактов (GET /api/contacts/paged)

bash
curl "$CRM_BASE_URL/api/contacts/paged?page=0&size=20&search=Petrov&sort=createdAt,desc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

7. Сделки

7.1. Создание сделки (POST /api/deals/create)

bash
curl -X POST "$CRM_BASE_URL/api/deals/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Server hardware delivery",
    "clientId": "9f128931-69fd-493a-9a08-be5be0e6603d",
    "statusId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
    "stageId": "dddd0001-0000-0000-0000-000000000001",
    "probability": 60,
    "amount": 150000.00,
    "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
  }'

Основные поля:

ПолеТипОбязательноОписание
namestringдаНазвание сделки
clientIduuidдаID клиента
statusIduuidнетСтатус (статус стадии)
stageIduuidнетСтадия продаж
probabilityintegerнетВероятность 0–100
amountnumberнетСумма
plannedAmountnumberнетПлановая сумма
discountPercentintegerнетСкидка 0–100
startDate / expectedCloseDatedate-timeнетДаты
ownerIduuidнетВладелец
leadIduuidнетСвязанный лид
contactIduuidнетСвязанный контакт
productIdsuuid[]нетПродукты (упрощённый формат)
dealProductsarrayнетПозиции сделки (полный формат)
dealPartiesarrayнетСтороны сделки

7.2. Постраничное чтение сделок (GET /api/deals/paged)

bash
curl "$CRM_BASE_URL/api/deals/paged?page=0&size=20&stageKind=OPEN&sort=createdAt,desc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

Основные фильтры: name (ILIKE), clientId, clientName, statusId, stageId, stageKind (OPEN/WON/LOST), ownerId, search, startDateFrom/startDateTo, expectedCloseDateFrom/expectedCloseDateTo, actualCloseDateFrom/actualCloseDateTo, createdAtFrom/createdAtTo.

8. Маркетинговые события (атрибуция)

Для отправки UTM-меток, рекламных идентификаторов и источников трафика используйте:

POST /api/dashboard/marketing/events

bash
curl -X POST "$CRM_BASE_URL/api/dashboard/marketing/events" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "eventType": "lead_submitted",
    "occurredAt": "2026-09-05T20:00:00Z",
    "visitorId": "visitor-8b7f",
    "sessionId": "session-31ac",
    "leadId": "22222222-2222-2222-2222-222222222222",
    "externalId": "site-form-submit-20260905-000123",
    "source": "website",
    "channel": "paid",
    "utmSource": "google",
    "utmMedium": "cpc",
    "utmCampaign": "summer-consulting",
    "utmContent": "banner-a",
    "utmTerm": "crm consultation",
    "gclid": "EAIaIQobChMI-example",
    "landingUrl": "https://www.example.com/consultation",
    "referrer": "https://www.google.com/",
    "metadata": {
      "formName": "consultation",
      "pageType": "landing"
    }
  }'

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

json
{
  "accepted": true,
  "duplicate": false,
  "eventId": "33333333-3333-3333-3333-333333333333"
}

Правила:

Подробности см. в site-leads-integration-guide.md.

9. Экспорт данных (NDJSON)

Эндпоинты экспорта возвращают все записи тенанта в формате NDJSON (один JSON-объект на строку, \n-разделённые).

ЭндпоинтОписание
GET /api/export/leadsВсе лиды тенанта
GET /api/export/clientsВсе клиенты тенанта
GET /api/export/contactsВсе контакты тенанта
bash
curl "$CRM_BASE_URL/api/export/leads" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

Пример ответа (поток строк):

text
{"id":"550e8400-e29b-41d4-a716-446655440001","message":"Website inquiry","quality":"WARM","statusName":"New","createdAt":"2026-08-20T10:00:00+03:00","ownerName":"Ivan Ivanov","clientName":"Romashka LLC","contactFirstName":"Petr","contactLastName":"Petrov","leadSourceName":"Paid search"}
{"id":"550e8400-e29b-41d4-a716-446655440002","message":"Phone call","quality":"COOL","statusName":"In progress","createdAt":"2026-08-19T09:00:00+03:00","ownerName":"Maria Smirnova","clientName":null}

Важно: NDJSON не является корректным JSON-массивом. Читайте ответ построчно через ReadableStream (не вызывайте JSON.parse() для всего ответа).

10. Сквозной пример интеграции

Следующий сценарий создаёт лид с сайта, связывает контакт и клиента, создаёт сделку и отправляет маркетинговое событие.

bash
CRM_BASE_URL=https://crm.example.com
CRM_TOKEN="<access-token>"

# 1. Вход
curl -s -X POST "$CRM_BASE_URL/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"username": "integration", "password": "secret123"}' | tee /tmp/login.json

CRM_TOKEN=$(jq -r '.token' /tmp/login.json)

OWNER_ID=$(curl -s "$CRM_BASE_URL/api/users/paged?page=0&size=50" \
  -H "Authorization: Bearer $CRM_TOKEN" | jq -r '.content[0].id')

# 2. Создание клиента
curl -s -X POST "$CRM_BASE_URL/api/clients/create" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"type\": \"COMPANY\",
    \"name\": \"Romashka LLC\",
    \"taxId\": \"7700000001\",
    \"country\": \"RU\",
    \"ownerId\": \"$OWNER_ID\",
    \"authorId\": \"$OWNER_ID\"
  }" | tee /tmp/client.json

CLIENT_ID=$(jq -r '.id' /tmp/client.json)

# 3. Создание контакта
curl -s -X POST "$CRM_BASE_URL/api/contacts/create" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"firstName\": \"Ivan\",
    \"lastName\": \"Petrov\",
    \"countryCode\": \"RU\",
    \"ownerId\": \"$OWNER_ID\",
    \"authorId\": \"$OWNER_ID\"
  }" | tee /tmp/contact.json

CONTACT_ID=$(jq -r '.id' /tmp/contact.json)

# 4. Создание лида
curl -s -X POST "$CRM_BASE_URL/api/leads/create" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"message\": \"Website inquiry\",
    \"clientId\": \"$CLIENT_ID\",
    \"contactId\": \"$CONTACT_ID\",
    \"ownerId\": \"$OWNER_ID\",
    \"authorId\": \"$OWNER_ID\",
    \"quality\": \"WARM\"
  }" | tee /tmp/lead.json

LEAD_ID=$(jq -r '.id' /tmp/lead.json)

# 5. Создание сделки, связанной с лидом
curl -s -X POST "$CRM_BASE_URL/api/deals/create" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"name\": \"Consultation for Ivan Petrov\",
    \"clientId\": \"$CLIENT_ID\",
    \"leadId\": \"$LEAD_ID\",
    \"contactId\": \"$CONTACT_ID\",
    \"amount\": 50000.00,
    \"ownerId\": \"$OWNER_ID\",
    \"authorId\": \"$OWNER_ID\"
  }"

# 6. Отправка маркетингового события
curl -s -X POST "$CRM_BASE_URL/api/dashboard/marketing/events" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"eventType\": \"lead_submitted\",
    \"occurredAt\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",
    \"leadId\": \"$LEAD_ID\",
    \"externalId\": \"request-$(uuidgen)\",
    \"source\": \"website\",
    \"channel\": \"direct\",
    \"landingUrl\": \"https://www.example.com/form\",
    \"metadata\": {\"formName\": \"consultation\"}
  }"

11. Идемпотентность и обработка ошибок

12. Быстрый старт

  1. Аутентифицируйтесь через POST /api/auth/login; сохраните token и refreshToken.
  2. Добавляйте Authorization: Bearer <token> к каждому запросу. При 401 обновите через /api/auth/refresh.
  3. Получите справочники (пользователи/статусы/стадии/источники лидов) один раз и закэшируйте UUID.
  4. Создавайте сущности в логичном порядке: клиент → контакт → лид → сделка.
  5. Используйте постраничные эндпоинты для чтения с серверной фильтрацией и сортировкой.
  6. Для экспорта используйте NDJSON-эндпоинты и читайте поток построчно.
  7. Для массового приёма используйте batch-эндпоинты (/api/leads/import/batch, /api/clients/import/batch) с поддержкой отката.
  8. Отправляйте маркетинговую атрибуцию через POST /api/dashboard/marketing/events со стабильным externalId.
  9. Никогда не храните и не передавайте персональные данные в metadata маркетингового события.
  10. См. подробную документацию по каждому API: site-leads-integration-guide.md.