API Эндпоинты для POS интеграции#
Полная документация API эндпоинтов для интеграции с кассовой системой и работы с бонусной программой.
Базовый URL#
Production: https://gateway.sagi.kz
Sandbox: https://test.sagi.kz
Все запросы требуют авторизации через JWT токен в заголовке Authorization: Bearer {token}.
ВАЖНОЕ ПРИМЕЧАНИЕ#
Все эндпоинты API возвращают результат в следующем формате:
type Response struct {
Code int32 `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
В документации ниже показано только содержимое поля data для упрощения чтения. В реальных ответах API все данные будут обернуты в структуру Response.
Пример реального ответа:
{
"code": 200,
"message": "Success",
"data": {
"id": 1460220481801031680,
"phone": "+77071234567",
"first_name": "Иван"
}
}
1. Поиск клиента#
GET /api/v1/promoters/find#
Поиск клиента по номеру телефона для работы с бонусной программой.
Query параметры:
phone(string, обязательный) - номер телефона клиента (формат: +77071234567)branch_id(int64, обязательный) - ID филиала для проверки черного списка
Пример запроса:
curl -X GET "{{baseURL}}/api/v1/promoters/find?phone=+77071234567&branch_id=1234567890123456" \
-H "Authorization: Bearer {token}"
Успешный ответ (200) - объект User (Пользователь):
{
"id": 1460220481801031680,
"first_name": "Иван",
"last_name": "Иванов",
"birthday": "02-10-2025",
"avatar": "https://storage.example.com/avatars/user.jpg",
"phone": "+77071234567",
"username": "",
"tags": [
{
"id": 128390023012930123,
"name": "Соседи по дому",
"bonus_percentage": 50,
"background_color": "",
"color": "",
"created_at": 1761647590144,
"updated_at": 1761647590144,
"user_count": 0,
"is_discount": false
}
],
"send_code_for_use_cashback": true,
"gradation_status": ""
}
Ошибки:
404- Пользователь не найден400- Неверный формат телефона403- Пользователь в черном списке филиала
2. Редактирование личных данных клиента#
PUT /api/v1/customers/{user_id}/personal-info#
Редактирование ФИО и даты рождения клиента.
Тело запроса:
{
"first_name": "Иван",
"last_name": "Иванов",
"birthday": "15-03-1990", // формат DD-MM-YYYY
"phone_number": "+77071234567",
"new_phone_number": "+77716254424",
"branch_id": 12399231239344,
"tags": [23412432412341, 32142341234234, 12341234344934]
}
Пример запроса:
curl -X PUT "{{baseURL}}/api/v1/customers/1460220481801031680/personal-info" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Иван",
"last_name": "Иванов",
"birthday": "15-03-1990"
}'
Успешный ответ (200) - объект User (Пользователь):
{
"id": 1460220481801031680,
"phone": "+77071234567",
"first_name": "Иван",
"last_name": "Иванов",
"birthday": "1990-03-15T00:00:00Z"
}
3. Получение баланса клиента в филиале#
GET /api/v1/branches/{branch_id}/private/balance#
Получение доступных бонусов клиента в конкретном филиале.
Query параметры:
user_id(int64, обязательный) - ID пользователяgroup_id(int64, обязательный) - Group ID филиала
Пример запроса:
curl -X GET "{{baseURL}}/api/v1/branches/1234567890123456/private/balance?user_id=1460220481801031680&group_id=9876543210987654" \
-H "Authorization: Bearer {token}"
Успешный ответ (200) - число (float64):
2500.50
4. Получение информации о частном филиале клиента#
GET /api/v1/branches/{branch_id}/customers/{user_id}/private-branch#
Получение детальной информации о клиенте в филиале.
Пример запроса:
curl -X GET "{{baseURL}}/api/v1/branches/1234567890123456/customers/1460220481801031680/private-branch" \
-H "Authorization: Bearer {token}"
Успешный ответ (200) - объект PrivateBranch (Частный филиал):
{
"branch_id": 1234567890123456,
"group_id": 9876543210987654,
"balance": 2500.50,
"is_client": true,
"cash_back_percent": 5.0,
"daily_tx_count": 2,
"daily_tx_limit": 5,
"spend_amount": 45000.0,
"updated_at": 1705332000000
}
5. Получение процента кешбека клиента#
GET /api/v1/branches/{branch_id}/cashback#
Получение актуального процента кешбека для клиента с учетом всех условий и ограничений.
Query параметры:
user_id(int64, обязательный) - ID клиентаtype(string, опциональный) - тип заказа («direct», «qr»)use_certificate(boolean, опциональный) - использование сертификата
Пример запроса:
curl -X GET "{{baseURL}}/api/v1/branches/1234567890123456/cashback?user_id=1460220481801031680" \
-H "Authorization: Bearer {token}"
Успешный ответ (200) - число (float64):
5.0
Логика расчета:
Проверяется наличие клиента в черном списке филиала
Учитывается дневной лимит транзакций (если превышен → кешбек = 0)
Применяются градационные настройки кешбека
Возвращается максимальный процент из доступных
Ошибки:
400- Клиент в черном списке филиала404- Филиал или клиент не найден
6. Получение информации о штампах клиента#
GET /api/v1/branches/{branch_id}/customers/{user_id}/award#
Получение детальной информации о накопленных штампах и доступных наградах клиента.
Пример запроса:
curl -X GET "{{baseURL}}/api/v1/branches/1234567890123456/customers/1460220481801031680/award" \
-H "Authorization: Bearer {token}"
Успешный ответ (200) - объект UserAward (Награда пользователя):
{
"id": "60f1b2b3c4d5e6f7g8h9i0j1",
"title": "Бесплатный кофе",
"description": "Получите бесплатный кофе за 10 покупок",
"stamp_count": 10,
"received_stamp_count": 7,
"created_at": 1642204800000,
"activated_at": 1642204800000,
"expired_at": 1735689600000,
"total": 3,
"is_active": true
}
Случай отсутствия данных:
Если клиент еще не участвовал в программе наград, возвращаются настройки филиала с received_stamp_count: 0.
Бизнес-логика:
Если
received_stamp_count>=stamp_count→ клиент может получить наградуПрограмма наград должна быть активна (
is_active = true)
7. Выдача награды клиенту#
POST /api/v1/branches/{branch_id}/awards/{award_id}/give#
Выдача подарка клиенту при достижении необходимого количества штампов.
Тело запроса:
{
"user_id": 1460220481801031680,
"stamp_count": 10
}
Пример запроса:
curl -X POST "{{baseURL}}/api/v1/branches/1234567890123456/awards/60f1b2b3c4d5e6f7g8h9i0j1/give" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"user_id": 1460220481801031680,
"stamp_count": 10
}'
Успешный ответ (200) - объект UserAward (Награда пользователя):
{
"id": "60f1b2b3c4d5e6f7g8h9i0j1",
"title": "Бесплатный кофе",
"description": "Получите бесплатный кофе за 10 покупок",
"stamp_count": 10,
"received_stamp_count": 0,
"total": 4,
"updated_at": 1705332000000
}
Условия:
Клиент должен иметь достаточное количество штампов
Программа наград должна быть активна в филиале
Счетчик штампов сбрасывается к 0 после выдачи награды
8. Создание транзакции для начисления бонусов#
POST /api/v1/branches/{branch_id}/cash/order#
Создание транзакции для начисления или списания бонусов.
Тело запроса:
{
"user_id": 1460220481801031680, // ID клиента (обязательное)
"amount": 2000, // сумма покупки в тенге (обязательное)
"bonus_amount": 1000, // сумма списываемых бонусов (0 если не списываем)
"comment": "Покупка в кассе #1", // комментарий к транзакции (опционально)
"user_phone": "+77077000087", // телефон для незарегистрированных клиентов (опционально)
"add_stamp": false, // начислить штампик true/false (опционально)
"stamp_count": 1, // количество начисляемых штампиков (опционально)
"give_award": false, // выдается ли награда true/false (опционально)
"use_balance_code": "123456" // код подтверждения для списания (требуется при bonus_amount > 0)
}
Описание полей:
user_id- уникальный идентификатор клиента в системеamount- общая сумма покупки в тенгеbonus_amount- сумма к списанию с баланса бонусов (0 = только начисление)comment- произвольный комментарий, отображается в историиuser_phone- используется для создания нового клиента, еслиuser_idне указанadd_stamp- добавить штамп в программу наград (не может быть true одновременно сgive_award)stamp_count- количество штампов к добавлениюgive_award- выдается ли награда (не может быть true одновременно сadd_stamp)use_balance_code- код подтверждения, отправленный клиенту SMS (обязателен при списании бонусов)
Пример запроса:
curl -X POST "{{baseURL}}/api/v1/branches/1234567890123456/cash/order" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"user_id": 1460220481801031680,
"amount": 2000,
"bonus_amount": 0,
"comment": "Покупка в кассе #1",
"user_phone": "+77077000087",
"add_stamp": true,
"stamp_count": 1,
"give_award": false
}'
Успешный ответ (201) - объект Order (Заказ):
{
"id": 12345678901234567890,
"order_number": 1001,
"type": "direct",
"status": "CREATED",
"initial_order_total_amount": 2000.0,
"order_total_amount": 2000.0,
"created_at": 1705332000000,
"sender": {
"id": 1460220481801031680,
"first_name": "Иван",
"last_name": "Иванов",
"phone": "+77077000087"
},
"recipient": {
"id": 1234567890123456,
"name": "Кофейня Аромат",
"address": "ул. Абая 10"
}
}
Важные правила:
add_stampиgive_awardне могут быть одновременноtrueuse_balance_codeобязателен приbonus_amount> 0 и если филиал требует код подтверждения
9. Завершение транзакции и начисление бонусов#
POST /api/v1/orders/{order_id}/cash/complete#
Завершение транзакции и фактическое начисление/списание бонусов клиенту.
Тело запроса:
{
"use_balance": false, // списывались ли бонусы (true/false)
"amount": 0, // сумма списанных бонусов (обязательно указать при use_balance=true)
"payment_method": "cash" // способ оплаты: cash, card, online, mixed
}
Описание полей:
use_balance- ОБЯЗАТЕЛЬНО true при списании бонусов, false при начисленииamount- при СПИСАНИИ указать желаемую сумму списания, при начислении указать 0payment_method- способ оплаты остатка суммы после списания бонусов
Пример запроса (без списания бонусов):
curl -X POST "{{baseURL}}/api/v1/orders/12345678901234567890/cash/complete" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"use_balance": false,
"amount": 0,
"payment_method": "card"
}'
Пример запроса (со списанием 1000 тенге бонусов):
curl -X POST "{{baseURL}}/api/v1/orders/12345678901234567890/cash/complete" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"use_balance": true,
"amount": 1000,
"payment_method": "mixed"
}'
Успешный ответ (200):
null
При успешном завершении возвращается пустой ответ.
10. Отправка кода подтверждения для списания бонусов#
POST /api/v1/customers/{user_id}/send-use-cashback-code#
Отправка SMS кода подтверждения для списания бонусов клиента.
Тело запроса:
{
"branch_id": 1234567890123456
}
Пример запроса:
curl -X POST "{{baseURL}}/api/v1/customers/1460220481801031680/send-use-cashback-code" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"branch_id": 1234567890123456
}'
Успешный ответ (200) - строка (код):
"1234"
Ошибка неверного кода (400):
{
"code": 3025,
"message": "code for using private balance is wrong"
}
11. Отмена транзакции#
POST /api/v1/orders/{order_id}/revert-transaction#
Отмена транзакции и возврат начисленных бонусов. Также отменяет начисление штампов.
Тело запроса: пустое
Пример запроса:
curl -X POST "{{baseURL}}/api/v1/orders/12345678901234567890/revert-transaction" \
-H "Authorization: Bearer {token}"
Успешный ответ (200) - объект Order (Заказ):
{
"id": 12345678901234567890,
"status": "DECLINED",
"updated_at": 1705335600000,
"error": {
"code": 3015,
"message": "order was manually reverted"
}
}
Условия: Статус транзакции должен быть «COMPLETED».
12. Частичный возврат#
PATCH /api/v1/orders/{order_id}/refund#
Частичный возврат суммы и соответствующих бонусов. Штампы остаются.
Тело запроса:
{
"amount": "500" // сумма возврата как строка (не должна быть >= суммы транзакции)
}
Пример запроса:
curl -X PATCH "{{baseURL}}/api/v1/orders/12345678901234567890/refund" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"amount": "500"
}'
Успешный ответ (200) - объект Order (Заказ):
{
"id": 12345678901234567890,
"updated_at": 1705335600000,
"initial_order_total_amount": 2000.0,
"order_total_amount": 1500.0,
"refunds": [
{
"amount": 500.0,
"refunded_bonus": 25.0,
"created_at": 1705335600000
}
]
}
Условия:
Статус транзакции должен быть «COMPLETED»
Сумма возврата не должна быть больше или равна сумме транзакции
Поле
amountпередается как строка
13. Обновление токена авторизации#
POST /api/v1/auth/refresh_token#
Обновление истекшего JWT токена с помощью refresh token.
Заголовки:
Authorization: Bearer {expired_token}- истекший токенContent-Type: application/json
Тело запроса: пустое
Пример запроса:
curl -X POST "{{baseURL}}/api/v1/auth/refresh_token" \
-H "Authorization: Bearer {expired_token}"
Успешный ответ (200):
{
"code": 200,
"expire": "2024-03-16T14:30:00Z",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Ошибки:
401- Токен недействителен или не может быть обновлен403- Refresh token истек
Примечания:
Используется для автоматического обновления токенов в POS системах
Рекомендуется настроить cron-задачу для периодического обновления