API

Открытый API сделок и вебхуки CRM

Обновлено 28 сентября 2026 г.9 мин чтения

Сделки Chato можно вести из своей программы: сайт создаёт сделку по заявке, 1С закрывает её после оплаты, склад ставит задачу менеджеру. Обратно Chato сообщает вашей программе, что произошло в CRM: сделку перенесли, выиграли, поменяли ответственного.

Настраивается в кабинете: Сделки → ⋯ → Настройки → API и вебхуки (видят администратор и владелец). Там же ссылка на справочник всех запросов — Swagger: https://chato.kz/api/v1/public/docs, описание в формате OpenAPI — https://chato.kz/api/v1/public/openapi.json.

Ключ API

Нажмите Новый ключ, дайте ему название («Сайт», «1С») и отметьте права:

Право Что разрешает
deals:read читать сделки, их примечания
deals:write создавать, менять, переносить, закрывать, удалять сделки, писать примечания
contacts:read / contacts:write искать / создавать и менять контакты
tasks:read / tasks:write читать / ставить и выполнять задачи
pipelines:read воронки, этапы, доп. поля, причины отказа
users:read список сотрудников (для responsibleUserId)
messages:send писать клиентам

Ключ показывается один раз — сразу скопируйте его. Chato хранит только его отпечаток и не сможет показать ключ снова. В списке видно, кто выпустил ключ и когда им пользовались в последний раз. Отозвать — ключ перестаёт работать сразу, программа получит 401.

Ключ — как пароль: храните его на сервере, в переменных окружения. Никогда не кладите его в код сайта, который видит браузер посетителя.

Всё, что программа делает по ключу, записывается в историю сделки от имени того, кто выпустил ключ, с пометкой «через API». Ключ не может больше, чем его автор: если сотруднику скрыта воронка, по его ключу она тоже скрыта. Автоматизации этапов, уведомления и живое обновление доски у коллег срабатывают так же, как при работе в кабинете.

Как отправлять запросы

https://chato.kz/api/v1/public
Authorization: Bearer chato_sk_...
Content-Type: application/json

Ключ можно передать и заголовком X-Api-Key. Успешный ответ всегда лежит в поле data.

  • Лимит — 120 запросов в минуту на ключ. Сверх него — 429 и заголовок Retry-After (через сколько секунд повторить). Остаток виден в X-RateLimit-Remaining. У каждого ключа свой счётчик: одна программа не съедает лимит другой.
  • Повтор без дублей — добавьте к POST заголовок Idempotency-Key (любая строка до 255 символов, например id заявки у вас). Повтор с тем же ключом в течение суток вернёт первый ответ с заголовком Idempotent-Replayed: true и не создаст вторую сделку. Тот же ключ с другим телом — 422 IDEMPOTENCY_KEY_REUSED.

Ошибки

Ошибка всегда одного вида:

{
  "error": {
    "code": "REQUIRED_FIELDS",
    "message": "Заполните поля, чтобы перенести в «Договор подписан»",
    "textCode": "REQUIRED_FIELDS",
    "params": { "stage": "Договор подписан" },
    "details": { "missing": [{ "key": "data_dogovora", "label": "Дата договора", "type": "DATE" }] }
  },
  "statusCode": 422
}
Код Когда
401 UNAUTHORIZED нет ключа, ключ неверный или отозван
403 FORBIDDEN_SCOPE у ключа нет нужного права
404 DEAL_NOT_FOUND и т. п. нет такого объекта в вашей компании (чужие id всегда дают 404)
400 VALIDATION_FAILED неверные данные, список — в details.validation
422 REQUIRED_FIELDS для этапа нужны обязательные поля — какие, в details.missing
422 LOSS_REASON_REQUIRED перенос в «Отказ» без причины, а воронка её требует
429 RATE_LIMITED превышен лимит, смотрите Retry-After

Справочники

curl https://chato.kz/api/v1/public/pipelines -H "Authorization: Bearer $CHATO_KEY"

Воронки с этапами (kind: OPEN — рабочий, WON — «Успешно», LOST — «Отказ»). Остальное:

  • GET /deal-fields — доп. поля: key (код поля — по нему пишутся значения), тип, варианты, на каких этапах обязательно;
  • GET /loss-reasons — причины отказа;
  • GET /users — сотрудники (id, имя, почта, роль).

Сделки

Создать

curl -X POST https://chato.kz/api/v1/public/deals \
  -H "Authorization: Bearer $CHATO_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: site-order-10542' \
  -d '{
    "pipelineId": "PIPELINE_ID",
    "title": "Заявка с сайта",
    "amount": 150000,
    "contact": { "name": "Айгерим", "phone": "+7 701 555 11 22", "email": "aigerim@example.com" },
    "tags": ["сайт"],
    "fields": { "gorod": "almaty", "obem": 40 }
  }'

Контакт — contactId или contact. По contact Chato сначала ищет человека: по телефону (последние 10 цифр, формат любой), затем по e-mail (без учёта регистра); не нашёл — создаёт. В ответе contactCreated показывает, что произошло. Без pipelineId и stageId сделка встаёт в первый этап первой воронки. Ответственный по умолчанию — автор ключа; "responsibleUserId": null — без ответственного. Источник сделки — «API».

Доп. поля — объект fields по кодам из /deal-fields: для списка — id варианта, для множественного выбора — массив, для даты — 2026-09-28, для флажка — true/false. Неверное значение — 400 с названием поля.

Изменить

curl -X PATCH https://chato.kz/api/v1/public/deals/DEAL_ID \
  -H "Authorization: Bearer $CHATO_KEY" -H 'Content-Type: application/json' \
  -d '{"amount": 180000, "tags": ["сайт", "vip"], "fields": {"oplata": "invoice"}}'

Меняется только присланное. tags заменяют прежний список, null в поле очищает его.

Перенести, закрыть

# в этап — с теми же правилами, что на доске
curl -X POST https://chato.kz/api/v1/public/deals/DEAL_ID/move \
  -H "Authorization: Bearer $CHATO_KEY" -H 'Content-Type: application/json' \
  -d '{"stageId": "STAGE_ID", "fields": {"data_dogovora": "2026-09-28"}}'

# успешно
curl -X POST https://chato.kz/api/v1/public/deals/DEAL_ID/close \
  -H "Authorization: Bearer $CHATO_KEY" -H 'Content-Type: application/json' \
  -d '{"result": "won"}'

# отказом — с причиной из /loss-reasons
curl -X POST https://chato.kz/api/v1/public/deals/DEAL_ID/close \
  -H "Authorization: Bearer $CHATO_KEY" -H 'Content-Type: application/json' \
  -d '{"result": "lost", "lossReasonId": "REASON_ID", "lossComment": "выбрали другого"}'

Если у этапа есть обязательные поля, а в сделке они пустые, придёт 422 REQUIRED_FIELDS со списком полей — повторите запрос, добавив их в fields. close ищет первый этап «Успешно» / «Отказ» воронки сделки; нужен другой — передайте его stageId.

Найти, прочитать, удалить

curl 'https://chato.kz/api/v1/public/deals?pipelineId=PIPELINE_ID&status=open&limit=50' \
  -H "Authorization: Bearer $CHATO_KEY"

Ответ: {"data": {"items": [...], "nextCursor": "..."}}. Следующая страница — тот же запрос с &cursor=<nextCursor>; nextCursor: null — страниц больше нет. Фильтры: pipelineId, stageId, status (open, won, lost, closed, unsorted), responsibleUserId (или none), contactId, tag, search (название, имя или номер клиента), updatedSince и createdSince (ISO-дата — удобно для синхронизации «что изменилось с прошлого раза»).

  • GET /deals/DEAL_ID — одна сделка;
  • DELETE /deals/DEAL_ID — в корзину на 30 дней (204); POST /deals/DEAL_ID/restore — вернуть.

Примечания и задачи

curl -X POST https://chato.kz/api/v1/public/deals/DEAL_ID/notes \
  -H "Authorization: Bearer $CHATO_KEY" -H 'Content-Type: application/json' \
  -d '{"text": "Оплата прошла в 1С"}'

curl -X POST https://chato.kz/api/v1/public/deals/DEAL_ID/tasks \
  -H "Authorization: Bearer $CHATO_KEY" -H 'Content-Type: application/json' \
  -d '{"kind": "CALL", "text": "Перезвонить", "dueAt": "2026-10-01T09:00:00+05:00"}'

curl -X POST https://chato.kz/api/v1/public/tasks/TASK_ID/complete \
  -H "Authorization: Bearer $CHATO_KEY" -H 'Content-Type: application/json' \
  -d '{"result": "Дозвонились"}'

GET /deals/DEAL_ID/notes и GET /deals/DEAL_ID/tasks — списки. Виды задач: CALL (звонок), MEETING (встреча), WRITE (написать), OTHER и свои (CUSTOM + customTypeId).

Контакты

  • GET /contacts?phone=87015551122 или ?email=... — найти (до 20);
  • POST /contacts {name, phone, email} — создать; если человек уже есть, вернётся он (200, "created": false), новый — 201;
  • PATCH /contacts/CONTACT_ID — поменять имя, телефон, e-mail.

Написать клиенту

С правом messages:send: POST /messages с conversationId или phone (для нового номера — ещё channelId), text и/или fileUrl — так же, как действие message входящей ссылки.

Вебхуки: события сделок на ваш адрес

Добавить адрес → впишите https-адрес и отметьте события. Сохраните — у адреса появится свой секрет подписи (кнопка «Показать»).

Событие Когда
deal.created сделка создана (в кабинете, по API, из обращения)
deal.updated поменялись название, сумма, теги, поля, ответственный
deal.stage_changed сделка перешла в другой этап
deal.won / deal.lost сделка закрыта успешно / отказом
deal.deleted / deal.restored в корзину / из корзины
deal.responsible_changed сменился ответственный
task.created / task.completed задача поставлена / выполнена
note.created добавлено примечание

На тот же адрес можно получать и события чатов (message.received, conversation.closed и другие — см. Вебхуки).

Chato отправляет POST:

{
  "id": "evt_3f2a9c...",
  "event": "deal.won",
  "createdAt": "2026-09-28T10:15:00.000Z",
  "workspaceId": "cmr4sk0ya0001o701hl7ghbqk",
  "data": {
    "deal": {
      "id": "cmulms3cp000r29eujik2dr1e",
      "title": "Заявка с сайта",
      "amount": 150000,
      "currency": "KZT",
      "status": "won",
      "pipeline": { "id": "...", "name": "Продажи" },
      "stage": { "id": "...", "name": "Успешно", "kind": "WON" },
      "contact": { "id": "...", "name": "Айгерим", "phone": "77015551122", "email": "aigerim@example.com" },
      "responsible": { "id": "...", "name": "Асхат", "email": "askhat@example.com" },
      "tags": ["сайт"],
      "fields": { "gorod": "almaty" },
      "closedAt": "2026-09-28T10:15:00.000Z"
    },
    "changes": {
      "stage": {
        "from": { "id": "...", "name": "Счёт выставлен", "kind": "OPEN" },
        "to": { "id": "...", "name": "Успешно", "kind": "WON" }
      }
    },
    "actor": { "type": "api", "userId": "..." }
  }
}

deal — снимок сделки в том же виде, что отдаёт API. changes — что поменялось (from → to; поля — как fields.<код>). actor.type: user (сотрудник в кабинете), api, webhook, automation, system. У task.* и note.created рядом с deal лежат task / note.

Заголовки: X-Chato-Event (событие), X-Chato-Event-Id (одинаков у повторов — по нему отбрасывайте дубли), X-Chato-Delivery, X-Chato-Timestamp, X-Chato-Signature.

Проверка подписи

X-Chato-Signature — это sha256= + HMAC-SHA256 секретом адреса от строки <X-Chato-Timestamp>.<сырое тело>. Считайте по сырому телу, до разбора JSON, и отбрасывайте запросы старше 5 минут.

Node.js (Express):

const crypto = require('node:crypto');
app.post('/chato', express.raw({ type: 'application/json' }), (req, res) => {
  const ts = req.get('X-Chato-Timestamp');
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.CHATO_WEBHOOK_SECRET)
    .update(`${ts}.${req.body}`)
    .digest('hex');
  const given = req.get('X-Chato-Signature') || '';
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  if (!fresh || given.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected))) {
    return res.sendStatus(401);
  }
  const event = JSON.parse(req.body);
  res.sendStatus(200); // ответьте сразу, тяжёлую работу — в фон
});

PHP:

$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_CHATO_TIMESTAMP'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, getenv('CHATO_WEBHOOK_SECRET'));
$given = $_SERVER['HTTP_X_CHATO_SIGNATURE'] ?? '';
if (abs(time() - (int) $ts) > 300 || !hash_equals($expected, $given)) {
    http_response_code(401);
    exit;
}
$event = json_decode($body, true);
http_response_code(200);

Python (Flask):

import hmac, hashlib, os, time
from flask import request, abort

@app.post("/chato")
def chato():
    body = request.get_data()  # сырые байты
    ts = request.headers.get("X-Chato-Timestamp", "")
    expected = "sha256=" + hmac.new(
        os.environ["CHATO_WEBHOOK_SECRET"].encode(), f"{ts}.".encode() + body, hashlib.sha256
    ).hexdigest()
    given = request.headers.get("X-Chato-Signature", "")
    if abs(time.time() - int(ts or 0)) > 300 or not hmac.compare_digest(expected, given):
        abort(401)
    event = request.get_json()
    return "", 200

Повторы, журнал, автоотключение

  • Успех — любой ответ 2xx в течение 10 секунд. Иначе Chato повторит через 1 мин, 5 мин, 30 мин, 2 ч и 6 ч — всего шесть попыток. Перенаправления (3xx) не выполняются.
  • Журнал доставок под адресом: статус, код ответа, число попыток, что отправлено и что ответил ваш сервер. Отправить ещё раз — повторная доставка с тем же id события. Журнал хранится 30 дней.
  • Если доставки не проходят подряд много раз (25 попыток), адрес выключается сам, а владелец и администраторы получают уведомление. Почините приёмник и нажмите Включить.
  • Проверить — отправляет тестовое событие ping. Новый секрет — старый перестаёт подходить сразу.

Отвечайте 200 сразу, а обработку делайте в фоне: долгий ответ Chato посчитает неудачей и повторит — а повтор придёт с тем же X-Chato-Event-Id, по которому его легко узнать.

Сделки через входящую ссылку

Если вы уже пользуетесь входящей ссылкой ассистента, она умеет и сделки — те же правила, что у API, в истории пометка «через вебхук»:

{ "action": "deal.create", "contact": { "name": "Айгерим", "phone": "+77015551122" }, "deal": { "title": "Заказ из 1С", "amount": 77000 } }
{ "action": "deal.move", "dealId": "DEAL_ID", "stageId": "STAGE_ID" }
{ "action": "deal.note", "dealId": "DEAL_ID", "text": "Оплата прошла" }
Открытый API сделок и вебхуки CRM — База знаний