Skip to content

Внешний API

Для клиентов, которым нужно читать и загружать данные в CRM извне — скриптом, ETL-процессом, другой системой, без браузера и без ручного логина. Ниже — реально работающий, проверенный функционал; известные ограничения перечислены в конце страницы.

Во всех примерах <slug> — адрес вашей CRM (https://<slug>.prohor.tech, либо ваш white-label домен).

1. Авторизация

API-ключ (рекомендуется для интеграций)

Ключи создаются в интерфейсе — Настройки CRM → API-ключи, кнопка «Создать ключ» (нужно право «Пользователи», manageUsers). Секрет вида pcrm_... показывается один раз, в момент создания — его нужно сразу сохранить на стороне интеграции.

Ключ передаётся заголовком в каждом запросе (оба варианта равнозначны):

bash
curl https://<slug>.prohor.tech/api/tenants/<slug> \
  -H "Authorization: Bearer pcrm_...секрет..."
bash
curl https://<slug>.prohor.tech/api/tenants/<slug> \
  -H "X-Api-Key: pcrm_...секрет..."

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

Логин + JWT (для браузерных сессий)

Это способ, которым авторизуется сам веб-интерфейс CRM; для серверных интеграций проще и надёжнее API-ключ выше — он не требует продлевать токен каждые 15 минут.

bash
curl -X POST https://<slug>.prohor.tech/api/auth/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{"email": "user@example.com", "password": "..."}'

Сервер выставляет access_token (JWT, 15 минут) и refresh_token (30 дней) как httpOnly cookie; продлить access_token без повторного логина — POST /api/auth/refresh. JWT можно передавать и явным заголовком Authorization: Bearer <access_token> вместо cookie.

2. Получение данных

Список каталогов (таблиц) с их полямиGET /api/tenants/<slug>/catalogs. Понадобится, чтобы знать field.id и field.type для чтения/записи значений.

Список записей каталога, с пагинацией/поиском/фильтрами/сортировкой:

bash
curl "https://<slug>.prohor.tech/api/tenants/<slug>/catalogs/<catalogId>/records?page=1&page_size=50&sort_field=created_at&sort_dir=desc" \
  -H "X-Api-Key: pcrm_..."
ПараметрОписание
searchполнотекстовый поиск по записям
sort_field, sort_dirsort_dirasc/desc
page, page_sizeпагинация
filter_logicAND или OR (заглавными)
filter[0][field], filter[0][op], filter[0][value]условие фильтра; индекс 0,1,2... для нескольких условий; opeq, neq, contains, gt, lt и др.

Также доступны: точечное чтение по id (.../records/by-ids?ids=...), список id, подпадающих под фильтр (.../records/ids?...), и агрегаты — группировка + сумма/среднее/количество (.../records/aggregate?groupBy=...&aggFunc=sum&aggField=...).

3. Создание, изменение, удаление записей

values — объект { "<fieldId>": <значение> }, где ключи — это id полей каталога, не их названия.

bash
curl -X POST https://<slug>.prohor.tech/api/tenants/<slug>/catalogs/<catalogId>/records \
  -H "Content-Type: application/json" -H "X-Api-Key: pcrm_..." \
  -d '{"values": {"<fieldId>": "Новая заявка №128"}}'
bash
curl -X PATCH https://<slug>.prohor.tech/api/tenants/<slug>/catalogs/<catalogId>/records/<recordId> \
  -H "Content-Type: application/json" -H "X-Api-Key: pcrm_..." \
  -d '{"values": {"<fieldId_статус>": "В работе"}}'
bash
curl -X DELETE https://<slug>.prohor.tech/api/tenants/<slug>/catalogs/<catalogId>/records/<recordId> \
  -H "X-Api-Key: pcrm_..."

Поля-связи и поля-пользователи

В values кладётся id целевой записи/пользователя (или JSON-массив id для мульти-значения), а не отображаемое название/имя — названия сервер сам подставляет только при чтении.

Массовые операции — для записей, уже существующих в CRM (не для создания пачки новых): массовое удаление (DELETE .../records с {"ids": [...]}) и массовое изменение одного поля (PATCH .../records/bulk-update с {"ids": [...], "field_id": "...", "value": "..."}).

4. Формат ошибок

СтатусКогда
200 / 204успех (204 — без тела, например отзыв ключа)
400некорректный запрос
401не авторизован (нет/невалиден токен, ключ отозван)
403не хватает прав
404не найдено (в т.ч. если запись недоступна по ограничению видимости группы — сервер не различает «не существует» и «нет доступа»)
json
{"error": {"message": "Unknown access group.", "details": null}}

5. Известные ограничения

Это сознательно отложенный функционал, не баг:

  • Нет bulk-эндпоинта для загрузки множества новых записей за один запрос — загрузка сегодня идёт по одной записи (POST .../records) на цикл.
  • Нет upsert по внешнему ключу. Чтобы не создавать дубли, интеграция должна сама сопоставлять «внешний ID → id записи в CRM» (например, хранить его в отдельном поле и перед созданием проверять фильтром по этому полю).
  • Один запрос — одна запись, без атомарного создания нескольких связанных записей за раз.

6. Полная спецификация (Swagger)

Интерактивная документация и актуальная OpenAPI-спецификация доступны по адресу /openapi.json/docs) на адресе вашей CRM.