Deals
The CRM layer of AISAR: deals attached to funnels and stages, deal tasks (calls, meetings, follow-ups), and per-company reference lists of deal types and lost reasons. Ownership of a deal or task is always checked by company_id — touching another company's record returns 404, not 403. Every endpoint requires an active subscription and the plan's deals feature.
Funnel/stage consistency
Updating a deal (POST /deals/{deal}) obeys funnel/stage consistency rules: changing funnel_id requires an explicit funnel_stage_id in the same request (otherwise 422 "A funnel_stage_id is required when changing funnel_id." — the old silent jump to the first stage was removed), and the funnel_stage_id itself must belong to the chosen funnel (otherwise 422 "Selected stage does not belong to the selected funnel."). If you change the stage without an explicit status, the status is derived from the stage type: success→won, failed→lost, anything else→open.
Closing a deal: won and lost
Moving status to lost (including implicitly, by moving into a failed-typed stage) requires a lost_reason_id from the lost-reasons reference or a free-form lost_reason (otherwise 422 "A lost reason is required when marking a deal as lost."); a transition to won/lost snapshots closed_amount/closed_currency at close time, and moving back to open clears closed_at, lost_reason, lost_reason_id and the amount snapshot.
Deletion and restore
Deleting a deal is soft (deleted_at, the id and dialog links are kept), and POST /deals/{deal}/restore (permission deal.delete) restores it idempotently.
Activity timeline
GET /deals/{deal}/activities returns an append-only timeline whose type is one of created|stage_changed|field_changed|note|task_created|task_completed|won|lost|responsible_changed|system; on system entries (automations, AI tools, inbound Bitrix24) actor is null.
Deal tasks
Deal tasks are updated with PATCH /deal-tasks/{task} (the legacy /deals/{deal} deliberately stays on POST): overdue is a derived field (due_at < now() while status=open), the mine filter aliases the current user, closing (done/cancelled) records completed_at, and changing assigned_user_id sends the assignee an in-app notification.
Reference lists and settings
Lost reasons (/lost-reasons; editing needs the lost_reason.manage permission) are unique by name within a company. The auto-creation settings (/company/deal-settings) return an already-resolved default_currency (defaulting to KZT when it is null in the database); auto_create_deal_enabled cannot be turned on without at least one funnel in the company (422).
Endpoints
| Method | Path | Summary |
|---|---|---|
| GET | /v1/dealsList deals (filters: funnel_id, status, contact_id, responsible_user_id) | List deals (filters: funnel_id, status, contact_id, responsible_user_id) |
| POST | /v1/dealsCreate a deal | Create a deal |
| GET | /v1/deals/{deal}Get a deal | Get a deal |
| POST | /v1/deals/{deal}Update a deal | Update a deal |
| DELETE | /v1/deals/{deal}Delete a deal (soft delete) | Delete a deal (soft delete) |
| POST | /v1/deals/{deal}/restoreRestore a soft-deleted deal | Restore a soft-deleted deal |
| GET | /v1/deals/{deal}/activitiesDeal activity feed (timeline) | Deal activity feed (timeline) |
| POST | /v1/deals/{deal}/notesAdd a note to the deal timeline | Add a note to the deal timeline |
| GET | /v1/deals/{deal}/tasksTasks attached to a deal | Tasks attached to a deal |
| GET | /v1/company/deal-settingsCompany deal auto-creation settings | Company deal auto-creation settings |
| POST | /v1/company/deal-settingsSave deal auto-creation settings | Save deal auto-creation settings |
| GET | /v1/deal-tasksList company tasks (filters: status, assigned_user_id, deal_id, overdue, mine) | List company tasks (filters: status, assigned_user_id, deal_id, overdue, mine) |
| POST | /v1/deal-tasksCreate a task | Create a task |
| PATCH | /v1/deal-tasks/{task}Update or close a task | Update or close a task |
| DELETE | /v1/deal-tasks/{task}Delete a task | Delete a task |
| GET | /v1/deal-typesList deal types | List deal types |
| POST | /v1/deal-typesCreate a deal type | Create a deal type |
| PATCH | /v1/deal-types/{dealType}Update a deal type | Update a deal type |
| DELETE | /v1/deal-types/{dealType}Delete a deal type | Delete a deal type |
| GET | /v1/lost-reasonsList lost reasons | List lost reasons |
| POST | /v1/lost-reasonsCreate a lost reason | Create a lost reason |
| PATCH | /v1/lost-reasons/{lostReason}Update a lost reason | Update a lost reason |
| DELETE | /v1/lost-reasons/{lostReason}Delete a lost reason | Delete a lost reason |
Examples
Create a deal
Request
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
}'Response
{
"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"
}
}Mark a deal as lost
Request
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
}'Response
{
"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"
}
}Mark a deal as lost (free-text reason)
Request
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": "Ушли к конкуренту"
}'Response
{
"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"
}
}Move a deal to another funnel (with a stage)
Request
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
}'Response
{
"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"
}
}Deal activity feed
Request
curl -X GET "https://api.aisar.app/v1/deals/501/activities?perPage=20" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"Response
{
"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 }
}
}Note on the deal timeline
Request
curl -X POST https://api.aisar.app/v1/deals/501/notes \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"body": "Клиент просит счёт на юрлицо"
}'Response
{
"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"
}
}
}Deal auto-creation settings
Request
curl -X GET https://api.aisar.app/v1/company/deal-settings \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"Response
{
"data": {
"auto_create_deal_enabled": true,
"default_funnel_id": 1,
"default_deal_title_template": "{contact_name}",
"default_currency": "KZT",
"has_funnels": true
}
}Save deal settings
Request
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"
}'Response
{
"data": {
"auto_create_deal_enabled": true,
"default_funnel_id": 1,
"default_deal_title_template": "{contact_name}",
"default_currency": "KZT",
"has_funnels": true
}
}List tasks (mine, overdue)
Request
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"Response
{
"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 }
}
}Create a deal task
Request
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
}'Response
{
"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"
}
}Close a task (PATCH)
Request
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"
}'Response
{
"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"
}
}Create a lost reason
Request
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
}'Response
{
"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"
}
}