Документация Личный кабинет

Документация API Axle

Интеграция внешних сервисов (POS/касса, собственные разработки) с платформой Axle: отправка данных к нам и чтение наших данных. Базовый адрес: https://axleapp.ru

Авторизация и ключи

Все запросы — по HTTPS. Ключ передаётся в заголовке Api-Key.

Api-Key: <ваш ключ>
Content-Type: application/json
Accept: application/json

Ключи бывают двух видов:

КлючГде взятьОсобенности
Открытый (для собственных интеграций) Кабинет: Интеграции → API Доступен на тарифе «Про». Работает с любого сервера.
Сервисный ключ POS Кабинет: Интеграции → Axle-CRM POS, блок «Ключ для входящих запросов» Для запросов самой кассы (вебхуки, чтение клиента). Принимается только с серверов POS. Тариф «Про» не требуется.

Перевыпуск любого ключа мгновенно отзывает старый. Не публикуйте ключи и не встраивайте их в клиентский код (сайт/приложение гостя).

Приём событий — POST /no-auth/api/v1/webhook/

Присылайте события при изменениях на вашей стороне. Тело — JSON с полем event, меткой source и данными. Ответ: { "success": true } (HTTP 200) либо ошибка с описанием (4xx).

1. client.upserted — профиль и агрегаты клиента

Создание/обновление клиента (мэтчинг у нас: по client_id → телефону → номеру карты). Поля — как в вашем client/list.

{
  "event": "client.upserted",
  "source": "pos",
  "client": {
    "client_id": 12345,
    "phone": "+79001234567",
    "card_number": "1234",
    "first_name": "Иван",
    "last_name": "Иванов",
    "middle_name": "Иванович",
    "sex": "male",                 // male | female | null
    "dob": "1990-01-15",          // YYYY-MM-DD | null
    "subscription_sms": true,
    "comment": "пример комментария",
    "bonus_balance": 500.00,       // текущий баланс бонусов (1 бонус = 1 ₽)
    "number_of_visits": 10,
    "average_bill_sum": 15000.00,  // итог покупок, ₽
    "loyalty_bill_sum": 9000.00,
    "loyalty_id": 1, "loyalty_name": "Базовая",
    "cohort_id": 2, "cohort_name": "Пример кампании",
    "last_visit_at": "2026-07-01T20:00:00+03:00",
    "updated_at": "2026-07-08T12:00:00+03:00"
  }
}

2. bonus.changed — изменился бонусный баланс

Лёгкое событие только про баланс (если не хотите слать весь профиль). Клиента ищем по client_id → телефону → номеру карты.

{
  "event": "bonus.changed",
  "source": "pos",
  "client": { "client_id": 12345, "bonus_balance": 650.00 }
}

3. receipt.closed — закрыт чек

Присылайте закрытый чек со строками (снимок названия/цены/количества на момент продажи). Чек попадает в историю покупок гостя и в аналитику (меню-инжиниринг, RFM) практически сразу. Суммы — в рублях (float), у нас хранятся в копейках. Объект shift необязателен (если чеки привязаны к сменам — присылайте).

{
  "event": "receipt.closed",
  "source": "pos",
  "receipt": {
    "receipt_id": 98765,
    "receipt_opened_at": "2026-07-08 19:02:11",
    "receipt_closed_at": "2026-07-08 20:15:40",
    "tile_name": "Стол 4", "tile_number": "4",
    "payed_amount": 2350.00,
    "is_fiscal": 1, "is_return": 0,
    "sales": [
      {
        "sale_id": 555001,
        "client_id": 12345,          // клиент строки (на шапке чека его нет)
        "price_id": 101,             // id позиции вашего прайса
        "menu_group_id": 7,
        "price_name": "Цезарь с курицей",
        "price_type_id": 1,          // 1 = обычная цена, 2 = повременная
        "price_menu": 590.00,        // цена за единицу по меню
        "quantity": 2,
        "payed_sum": 1080.00,        // фактически оплачено за строку
        "unit_name": "порц"
      }
    ]
  },
  "shift": { "shift_id": 3210 }      // необязательно
}

Скидка выводится у нас: price_menu × quantity − payed_sum (на строку и на чек). Повторная отправка того же receipt_id обновляет чек, дубли не создаются.

Чтение клиента — GET /no-auth/api/v1/customer/

Параметры (query): card или phone.

GET https://axleapp.ru/no-auth/api/v1/customer/?card=1234

{
  "success": true,
  "client": {
    "external_id": 100,          // наш id клиента
    "first_name": "Иван", "last_name": "Иванов", "middle_name": "Иванович",
    "phone": "+79001234567", "card_number": "1234",
    "sex": "male", "dob": "1990-01-15",
    "bonus_balance": 500.00
  }
}

Коды ответов и лимиты

КодКогда
200Успех. Тело: { "success": true, ... }.
401Нет заголовка Api-Key, ключ неверный или не проходит условия своего вида (открытый — организация не на тарифе «Про»; сервисный — запрос не с сервера POS).
404Клиент не найден (/customer/).
422Событие не распознано или не хватает данных — описание в message.
429Слишком много запросов: лимит 120 запросов в минуту с одного IP. Повторите позже.

Ответ ошибки всегда JSON: { "success": false, "message": "…" }.

Правила

ПравилоКак работает
Единицыbonus_balance — бонусы, 1 бонус = 1 ₽, до 2 знаков. Суммы чеков — рубли (float).
ИдемпотентностьПрисылайте updated_at; повтор с не более свежим временем игнорируется. Чеки идемпотентны по receipt_id.
Разрыв эхаЕсли изменение инициировали МЫ (пуш в вашу сторону), присылайте его обратно с source: "axle" — мы такое проигнорируем. Свои изменения — source: "pos".
УдалениеМягкое: помечаем неактивным, историю не трогаем.

Вопросы по интеграции и расширению форматов (доп. поля, новые события) — напишите нам, добавим.