Сделки
CRM-слой AISAR: сделки, привязанные к воронкам и стадиям, задачи по сделкам (звонки, встречи, follow-up), справочники типов сделок и причин отказа. Владение сделкой/задачей всегда проверяется по company_id — обращение к чужой записи возвращает 404, а не 403. Все эндпоинты требуют активную подписку и фичу плана deals.
Согласованность воронки и стадии
Обновление сделки (POST /deals/{deal}) подчиняется правилам согласованности воронки и стадии: смена funnel_id требует явного funnel_stage_id в том же запросе (иначе 422 «A funnel_stage_id is required when changing funnel_id.» — прежний тихий переход на первую стадию убран), а сам funnel_stage_id должен принадлежать выбранной воронке (иначе 422 «Selected stage does not belong to the selected funnel.»). Если сменить стадию без явного status, статус выводится из типа стадии: success→won, failed→lost, прочее→open.
Закрытие сделки: won и lost
Перевод status в lost (в том числе неявный — при переходе в стадию типа failed) требует lost_reason_id из справочника причин либо свободного lost_reason (иначе 422 «A lost reason is required when marking a deal as lost.»); переход в won/lost фиксирует снимок closed_amount/closed_currency на момент закрытия, а возврат в open очищает closed_at, lost_reason, lost_reason_id и снимок сумм.
Удаление и восстановление
Удаление сделки — мягкое (deleted_at, ID и связи диалогов сохраняются), а POST /deals/{deal}/restore (право deal.delete) восстанавливает её идемпотентно.
Таймлайн активности
GET /deals/{deal}/activities отдаёт append-only таймлайн со type из набора created|stage_changed|field_changed|note|task_created|task_completed|won|lost|responsible_changed|system; у системных записей (автоматизации, ИИ-инструменты, инбаунд Bitrix24) actor — null.
Задачи по сделкам
Задачи по сделкам обновляются методом PATCH /deal-tasks/{task} (легаси /deals/{deal} осознанно остаётся на POST): поле overdue — производное (due_at < now() при status=open), фильтр mine — алиас на текущего пользователя, закрытие (done/cancelled) фиксирует completed_at, а смена assigned_user_id шлёт ответственному in-app уведомление.
Справочники и настройки
Причины отказа (/lost-reasons; изменение — право lost_reason.manage) уникальны по имени в рамках компании. Настройки авто-создания (/company/deal-settings) отдают уже приведённое default_currency (дефолт KZT, если в БД null); включить auto_create_deal_enabled без единой воронки в компании нельзя (422).
Эндпоинты
| Метод | Путь | Описание |
|---|---|---|
| GET | /v1/dealsСписок сделок (фильтры: funnel_id, status, contact_id, responsible_user_id) | Список сделок (фильтры: funnel_id, status, contact_id, responsible_user_id) |
| POST | /v1/dealsСоздание сделки | Создание сделки |
| GET | /v1/deals/{deal}Получение сделки | Получение сделки |
| POST | /v1/deals/{deal}Обновление сделки | Обновление сделки |
| DELETE | /v1/deals/{deal}Удаление сделки (soft delete) | Удаление сделки (soft delete) |
| POST | /v1/deals/{deal}/restoreВосстановление мягко удалённой сделки | Восстановление мягко удалённой сделки |
| GET | /v1/deals/{deal}/activitiesЛента активности сделки (таймлайн) | Лента активности сделки (таймлайн) |
| POST | /v1/deals/{deal}/notesДобавить заметку в таймлайн сделки | Добавить заметку в таймлайн сделки |
| GET | /v1/deals/{deal}/tasksЗадачи, привязанные к сделке | Задачи, привязанные к сделке |
| GET | /v1/company/deal-settingsНастройки авто-создания сделок компании | Настройки авто-создания сделок компании |
| POST | /v1/company/deal-settingsСохранение настроек авто-создания сделок | Сохранение настроек авто-создания сделок |
| GET | /v1/deal-tasksСписок задач компании (фильтры: status, assigned_user_id, deal_id, overdue, mine) | Список задач компании (фильтры: status, assigned_user_id, deal_id, overdue, mine) |
| POST | /v1/deal-tasksСоздание задачи | Создание задачи |
| PATCH | /v1/deal-tasks/{task}Обновление/закрытие задачи | Обновление/закрытие задачи |
| DELETE | /v1/deal-tasks/{task}Удаление задачи | Удаление задачи |
| GET | /v1/deal-typesСписок типов сделок | Список типов сделок |
| POST | /v1/deal-typesСоздание типа сделки | Создание типа сделки |
| PATCH | /v1/deal-types/{dealType}Обновление типа сделки | Обновление типа сделки |
| DELETE | /v1/deal-types/{dealType}Удаление типа сделки | Удаление типа сделки |
| GET | /v1/lost-reasonsСписок причин отказа | Список причин отказа |
| POST | /v1/lost-reasonsСоздание причины отказа | Создание причины отказа |
| PATCH | /v1/lost-reasons/{lostReason}Обновление причины отказа | Обновление причины отказа |
| DELETE | /v1/lost-reasons/{lostReason}Удаление причины отказа | Удаление причины отказа |
Примеры
Создание сделки
Запрос
curl -X POST https://api.aisar.app/v1/deals \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"contact_id": 123,
"funnel_id": 1,
"funnel_stage_id": 3,
"title": "Office renovation",
"amount": "5000.00",
"currency": "KZT",
"source": "api",
"responsible_user_id": 5
}'Ответ
{
"data": {
"id": 501,
"company_id": 1,
"contact_id": 123,
"funnel_id": 1,
"funnel_stage_id": 3,
"title": "Office renovation",
"amount": "5000.00",
"currency": "KZT",
"status": "open",
"type_id": null,
"source": "api",
"utm_source": null,
"utm_medium": null,
"utm_campaign": null,
"probability": null,
"comments": null,
"begin_date": null,
"responsible_user_id": 5,
"expected_close_date": null,
"closed_at": null,
"lost_reason": null,
"lost_reason_id": null,
"closed_amount": null,
"closed_currency": null,
"stage_changed_at": "2026-03-15T10:00:00.000000Z",
"channel": null,
"custom_fields": null,
"created_at": "2026-03-15T10:00:00.000000Z",
"updated_at": "2026-03-15T10:00:00.000000Z"
}
}Перевод сделки в статус lost
Запрос
curl -X POST https://api.aisar.app/v1/deals/501 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "lost",
"lost_reason_id": 3
}'Ответ
{
"data": {
"id": 501,
"status": "lost",
"lost_reason_id": 3,
"lost_reason": null,
"closed_amount": "5000.00",
"closed_currency": "KZT",
"closed_at": "2026-03-17T09:00:00.000000Z",
"stage_changed_at": "2026-03-17T09:00:00.000000Z",
"updated_at": "2026-03-17T09:00:00.000000Z"
}
}Перевод сделки в lost (свободная причина)
Запрос
curl -X POST https://api.aisar.app/v1/deals/501 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "lost",
"lost_reason": "Ушли к конкуренту"
}'Ответ
{
"data": {
"id": 501,
"status": "lost",
"lost_reason_id": null,
"lost_reason": "Ушли к конкуренту",
"closed_amount": "5000.00",
"closed_currency": "KZT",
"closed_at": "2026-03-17T09:00:00.000000Z",
"stage_changed_at": "2026-03-15T10:00:00.000000Z",
"updated_at": "2026-03-17T09:00:00.000000Z"
}
}Смена воронки сделки (со стадией)
Запрос
curl -X POST https://api.aisar.app/v1/deals/501 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"funnel_id": 2,
"funnel_stage_id": 8,
"responsible_user_id": 5
}'Ответ
{
"data": {
"id": 501,
"funnel_id": 2,
"funnel_stage_id": 8,
"status": "open",
"responsible_user_id": 5,
"stage_changed_at": "2026-03-16T12:00:00.000000Z",
"updated_at": "2026-03-16T12:00:00.000000Z"
}
}Лента активности сделки
Запрос
curl -X GET "https://api.aisar.app/v1/deals/501/activities?perPage=20" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"Ответ
{
"data": {
"items": [
{
"id": 1,
"deal_id": 501,
"type": "stage_changed",
"actor_user_id": 5,
"body": null,
"metadata": { "from": 1, "to": 3 },
"created_at": "2026-03-15T10:05:00.000000Z",
"actor": { "id": 5, "name": "Ivan", "lastname": "Petrov" }
}
],
"pagination": { "page": 1, "perPage": 20, "total": 4, "lastPage": 1 }
}
}Заметка в таймлайн сделки
Запрос
curl -X POST https://api.aisar.app/v1/deals/501/notes \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"body": "Клиент просит счёт на юрлицо"
}'Ответ
{
"data": {
"message": "Note added.",
"item": {
"id": 902,
"deal_id": 501,
"type": "note",
"actor_user_id": 5,
"body": "Клиент просит счёт на юрлицо",
"metadata": null,
"created_at": "2026-03-16T09:00:00.000000Z"
}
}
}Настройки авто-создания сделок
Запрос
curl -X GET https://api.aisar.app/v1/company/deal-settings \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"Ответ
{
"data": {
"auto_create_deal_enabled": true,
"default_funnel_id": 1,
"default_deal_title_template": "{contact_name}",
"default_currency": "KZT",
"has_funnels": true
}
}Сохранение настроек сделок
Запрос
curl -X POST https://api.aisar.app/v1/company/deal-settings \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"auto_create_deal_enabled": true,
"default_funnel_id": 1,
"default_deal_title_template": "{contact_name}",
"default_currency": "KZT"
}'Ответ
{
"data": {
"auto_create_deal_enabled": true,
"default_funnel_id": 1,
"default_deal_title_template": "{contact_name}",
"default_currency": "KZT",
"has_funnels": true
}
}Список задач (свои, просроченные)
Запрос
curl -X GET "https://api.aisar.app/v1/deal-tasks?mine=1&overdue=1&perPage=20" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"Ответ
{
"data": {
"items": [
{
"id": 1,
"company_id": 1,
"deal_id": 501,
"contact_id": null,
"type": "call",
"title": "Перезвонить клиенту",
"description": null,
"due_at": "2026-07-08T09:00:00.000000Z",
"remind_at": "2026-07-08T08:45:00.000000Z",
"status": "open",
"assigned_user_id": 5,
"completed_at": null,
"overdue": true,
"created_at": "2026-07-07T10:00:00.000000Z",
"updated_at": "2026-07-07T10:00:00.000000Z"
}
],
"pagination": { "page": 1, "perPage": 20, "total": 7, "lastPage": 1 }
}
}Создание задачи по сделке
Запрос
curl -X POST https://api.aisar.app/v1/deal-tasks \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"deal_id": 501,
"type": "call",
"title": "Перезвонить клиенту",
"due_at": "2026-07-08T09:00:00Z",
"remind_at": "2026-07-08T08:45:00Z",
"assigned_user_id": 5
}'Ответ
{
"data": {
"id": 1,
"company_id": 1,
"deal_id": 501,
"contact_id": null,
"type": "call",
"title": "Перезвонить клиенту",
"description": null,
"due_at": "2026-07-08T09:00:00.000000Z",
"remind_at": "2026-07-08T08:45:00.000000Z",
"status": "open",
"assigned_user_id": 5,
"completed_at": null,
"overdue": false,
"created_at": "2026-07-07T10:00:00.000000Z",
"updated_at": "2026-07-07T10:00:00.000000Z"
}
}Закрытие задачи (PATCH)
Запрос
curl -X PATCH https://api.aisar.app/v1/deal-tasks/1 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "done"
}'Ответ
{
"data": {
"id": 1,
"deal_id": 501,
"type": "call",
"status": "done",
"assigned_user_id": 5,
"completed_at": "2026-07-08T09:30:00.000000Z",
"updated_at": "2026-07-08T09:30:00.000000Z"
}
}Создание причины отказа
Запрос
curl -X POST https://api.aisar.app/v1/lost-reasons \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Дорого",
"is_active": true,
"order": 0
}'Ответ
{
"data": {
"id": 1,
"company_id": 1,
"name": "Дорого",
"is_active": true,
"order": 0,
"created_at": "2026-07-07T10:00:00.000000Z",
"updated_at": "2026-07-07T10:00:00.000000Z"
}
}