API Анкоры
REST API для касс, 1С, CRM, сайтов, Zapier, Make и своих скриптов. Через него можно получить всех клиентов с картами и балансами, историю операций, начислить бонусы за покупку, списать кэшбэк и баллы, начислить штампы и выдать награду.
Запросы и ответы — JSON в UTF-8. Ключ доступа выдаёт сам бизнес в кабинете: Интеграции → «API и Zapier».
Адрес API
https://ankora.pro/api/v2/public
Спецификация OpenAPI 3.1
Импорт в Postman, Insomnia и генераторы клиентов.
Содержание
Начало работы
Быстрый старт Ключ и права Как указать клиента Ответы и ошибки Повтор запроса Списки и синхронизация Лимиты Вебхуки Сценарии с кодом Спецификация OpenAPI Аккаунт и состояние ключа Точки продажи Точка продажи Программы лояльности Программа лояльности Акции Список клиентов Найти или создать клиента Найти карту клиента Профиль клиента Изменить профиль клиента Найти карту Карта Рассчитать продажу Провести продажу Вернуть покупку Начислить вручную Списать Установить баланс Скорректировать баланс Изменить сумму покупок Начислить за покупку Списать кэшбэк или баллы Начислить штампы на карту Снять штампы Выдать награду Начислить штампы Выдать награду за штампы Продать абонемент Абонемент Засчитать визит Отменить визит Заморозить абонемент Разморозить абонемент Рассчитать возврат абонемента Вернуть абонемент Продать подписку Подписка Использовать действие Продлить подписку Поставить на паузу Снять с паузы Отменить подписку Засчитать визит Отменить визит История карты История операций Подписки на вебхуки Подписаться на события Подписка и журнал доставок Отписаться Отправить тестовое событиеСправочник
События вебхуков Объекты История измененийБыстрый старт
- В кабинете Анкоры откройте Интеграции → «API и Zapier» и нажмите «Включить API». Скопируйте ключ — он начинается с
ak_. - Проверьте ключ первым запросом — он вернёт ваш бизнес и состояние подписки:
curl https://ankora.pro/api/v2/public/account \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"- Найдите карту клиента — по телефону или номеру карты с QR на кассе:
curl -G https://ankora.pro/api/v2/public/cards/lookup \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
--data-urlencode "phone=+79991234567"- Проведите продажу: Анкора посчитает скидку, спишет бонусы и начислит новые по правилам программы.
curl -X POST https://ankora.pro/api/v2/public/cards/123/checkout \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"amount":1000,"redeem_cashback":200,"external_id":"CHEK-2026-000125","location_id":3}'Запросы и ответы — JSON в UTF-8, даты — ISO 8601, суммы — числа в рублях. Все методы — в справочнике ниже, у каждого — пример запроса, успешного ответа и ошибок.
Ключ и права
Каждый запрос — с заголовком Authorization: Bearer ak_…. Один ключ — один бизнес: все запросы идут в его клиентов, карты и программы, указывать бизнес не нужно. Ключ можно перевыпустить в кабинете — старый сразу перестанет работать. Не публикуйте ключ в коде сайта или мобильного приложения: он даёт доступ ко всей клиентской базе.
Нет ключа, ключ неверен или API выключен — ответ 401 unauthorized.
Права ключа
Чтение, начисление за покупки, списание бонусов, штампы, абонементы, подписки, визиты и клиенты работают с любым ключом. Операции, которые обходят правила программы, включаются отдельно на странице «API и Zapier» — по умолчанию они выключены:
| Право | Что открывает |
|---|---|
balance_management — «Управление балансами» | Начисление вручную, установка и корректировка кэшбэка, баллов и штампов, изменение суммы покупок для ступеней. |
refunds — «Возвраты и отмены» | Возврат покупки, возврат абонемента, отмена подписки. |
Без права — ответ 403 permission_denied с именем права в details.permission. Какие права у ключа сейчас — в GET /account.
Подписка бизнеса
Если подписка Анкоры истекла или API не входит в тариф, чтение продолжает работать, а операции возвращают 403 subscription_required с причиной в details.reason. Состояние видно заранее: api.operations_allowed в GET /account.
Как указать клиента и карту
У клиента по карте в каждой программе бизнеса. Методы над картой принимают её id в пути — /cards/{id}/…; найти карту можно через GET /cards/lookup любым идентификатором:
| Параметр | Что это |
|---|---|
card_id | Id карты в Анкоре — однозначно. |
card_number | Номер карты — то, что кассир сканирует с QR. Регистр и пробелы не важны. Однозначно. |
customer_id | Id клиента в Анкоре. |
phone | Телефон в любом российском формате: +79991234567, 8 999 123-45-67. |
external_customer_id | Id клиента в вашей системе — если вы уже передавали его вместе с телефоном, дальше клиент находится по нему. |
program_id | Программа, если у клиента карты в нескольких. Без него ответ program_required со списком программ клиента. |
Методы первой версии — POST /purchases, /redemptions, /stamps, /stamp_redemptions, GET /customers/search — принимают эти же параметры в теле запроса. Если клиент с картами в нескольких программах указан без program_id, они, как и раньше, берут первую активную программу.
Точка продажи — location_id у любой операции: покупки и списания попадут в аналитику по точкам. Список точек — GET /locations.
Ответы и ошибки
Успех — 200 или 201 с JSON. Ошибка — код HTTP и тело одного вида:
{
"error": "insufficient_balance",
"message": "Недостаточно кэшбэка: на карте 25 ₽, запрошено 50 ₽",
"details": { "currency": "cashback", "balance": 25.0, "requested": 50.0 }
}error — стабильный код: по нему ветвится ваш код. message — текст для человека, его можно показать кассиру; формулировка может меняться. details — подробности, свои у каждого кода.
| Код | HTTP | Когда | details |
|---|---|---|---|
unauthorized | 401 | Ключ не передан, неверен или API выключен. | — |
permission_denied | 403 | Операция выключена в правах ключа. | permission |
subscription_required | 403 | Подписка бизнеса истекла или API не входит в тариф. Чтение работает. | reason |
invalid_json | 400 | Тело запроса не разбирается как JSON. | — |
parameter_missing | 422 | Не передан обязательный параметр. | param или params — если нужен один из нескольких |
parameter_invalid | 422 | Параметр не того формата: сумма не число, дата не разбирается, неизвестное значение. | param |
not_found | 404 | Клиент, карта, программа, точка, абонемент, подписка или покупка не найдены у этого бизнеса. | resource |
program_required | 422 | У клиента карты в нескольких программах — передайте program_id. | program_ids |
mechanic_disabled | 422 | Механика выключена в программе: например, начисляют штампы, а штампов в программе нет. | mechanic |
insufficient_balance | 422 | Не хватает кэшбэка, баллов, штампов или наград. Ничего не списано. | currency, balance, requested |
redemption_limit_exceeded | 422 | Списание по чеку больше лимита программы — например, не больше 30% чека. | currency, max, requested |
limit_reached | 422 | Исчерпан лимит действия подписки или визит гостя уже засчитан сегодня. | — |
operation_rejected | 422 | Отказ по другому правилу Анкоры — причина в message: абонемент заморожен, у клиента уже есть подписка, телефон занят другим клиентом. | бывает |
idempotency_key_reused | 409 | Тот же Idempotency-Key пришёл с другим запросом. | — |
idempotency_key_in_progress | 409 | Запрос с этим ключом ещё выполняется — повторите через пару секунд. | — |
rate_limited | 429 | Больше 120 запросов в минуту на ключ. | retry_after_seconds |
internal_error | 500 | Сбой на стороне Анкоры. Повторите позже — с Idempotency-Key это безопасно. | — |
Повтор запроса
Сеть рвётся: запрос ушёл, а ответ не дошёл. Чтобы повтор не списал бонусы второй раз, передавайте в каждом POST, PUT, PATCH и DELETE заголовок Idempotency-Key — уникальную строку на операцию, до 255 символов: UUID или номер вашего документа.
- Повтор с тем же ключом в течение суток вернёт сохранённый ответ с заголовком
Idempotent-Replayed: true, а операция второй раз не выполнится. - Сохраняются только успешные ответы. Ошибка ничего не изменила — после исправления повторите с тем же ключом, операция выполнится.
- Тот же ключ с другим методом, адресом или телом —
409 idempotency_key_reused: для новой операции нужен новый ключ. - Ответ 500 тоже не сохраняется: повтор с тем же ключом безопасен.
curl -X POST https://ankora.pro/api/v2/public/cards/123/balance/spend \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: 9b2f7c1e-4a3d-4e8b-a6f0-2c5d8e1b7a94" \
-H "Content-Type: application/json" \
-d '{"currency":"cashback","amount":50}'Номер чека
У покупок свой надёжный ключ — номер чека external_id, он обязателен в POST /purchases и POST /cards/{id}/checkout. Чек с тем же номером не проведётся второй раз (ответ — skipped с причиной already_processed), а по номеру работает возврат POST /purchases/{external_id}/refund. Если списываете бонусы отдельно от покупки через POST /redemptions, передайте тот же external_id — возврат чека вернёт и списанное.
Списки и синхронизация
Списки — клиенты, операции, точки, программы, акции, подписки на вебхуки — отдаются страницами по возрастанию id:
{ "data": [ … ], "has_more": true, "next_after_id": 1234 }limit — от 1 до 100, по умолчанию 50. Следующая страница — с after_id из next_after_id; пока has_more равно true, есть ещё. На пустой странице next_after_id равен переданному after_id — с ним и приходите в следующий раз за новыми записями.
Выгрузить всю базу
import requests
API = "https://ankora.pro/api/v2/public"
HEADERS = {"Authorization": "Bearer ak_ВАШ_КЛЮЧ"}
after_id = 0
while True:
page = requests.get(f"{API}/customers", headers=HEADERS,
params={"after_id": after_id, "limit": 100}, timeout=30).json()
for customer in page["data"]:
save_customer(customer) # профиль и все карты с балансами
after_id = page["next_after_id"]
if not page["has_more"]:
breakЗабирать изменения
- Новые операции — GET /transactions с
after_id= последний полученный id. Операции не меняются, поэтому этого достаточно. - Изменившихся клиентов — GET /customers с
updated_since: клиент попадёт в выборку, если изменился профиль или любая из карт, включая баланс. - Чтобы не опрашивать вовсе — подпишитесь на вебхуки: Анкора пришлёт событие сама.
Лимиты
Не больше 120 запросов в минуту на ключ — с запасом для кассы и регулярной синхронизации. Сверх лимита — ответ 429 rate_limited и заголовок Retry-After: через сколько секунд можно продолжить. Для разовой большой выгрузки берите страницы по 100 записей; если лимита не хватает — напишите в поддержку.
Вебхуки
Анкора сама отправит POST-запрос на ваш адрес, как только событие случится, — опрашивать API не нужно. События:
card.created— Новый клиент программы — выпущена карта.customer.updated— Изменился профиль клиента.transaction.created— Новая операция по карте: покупка, начисление, списание, сгорание, абонемент, подписка.
Подписаться можно в кабинете (Интеграции → «API и Zapier» → «Вебхуки») или через POST /webhooks — так работают мгновенные триггеры Zapier. Адрес — только https и только публичный, до 10 подписок на ключ.
Что приходит
POST /ankora-webhook HTTP/1.1
Content-Type: application/json; charset=utf-8
Ankora-Event-Id: evt_6f1c2a9e-5b7d-4e8a-9c41-0d2b6f7e8a10
Ankora-Event-Type: transaction.created
Ankora-Signature: t=1761298200,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
{"id":"evt_6f1c2a9e-…","type":"transaction.created","created_at":"2026-10-24T12:30:00+03:00","business_id":42,"data":{…}}Данные — на момент события: карта в transaction.created показывает баланс сразу после операции, даже если доставка ушла позже.
Проверка подписи
Любой может отправить запрос на ваш адрес, поэтому прежде чем доверять данным, проверьте подпись. Ankora-Signature — это t=<время>,v1=<подпись>, где подпись — HMAC-SHA256 секретом подписки (whsec_…, виден в кабинете) от строки <t>.<тело запроса>. Считайте подпись от сырого тела — до разбора JSON — и отклоняйте запросы старше 5 минут: так старый запрос не повторить.
import hashlib, hmac, time
def ankora_signature_valid(secret: str, body: bytes, header: str, tolerance: int = 300) -> bool:
parts = dict(part.split("=", 1) for part in header.split(",") if "=" in part)
timestamp = int(parts.get("t", "0"))
if abs(time.time() - timestamp) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))const crypto = require("crypto");
function ankoraSignatureValid(secret, rawBody, header, tolerance = 300) {
const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
const timestamp = Number(parts.t);
if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > tolerance) return false;
const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
const given = Buffer.from(parts.v1 || "");
return given.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), given);
}function ankora_signature_valid(string $secret, string $body, string $header, int $tolerance = 300): bool {
$parts = [];
foreach (explode(',', $header) as $part) {
[$key, $value] = array_pad(explode('=', $part, 2), 2, '');
$parts[$key] = $value;
}
$timestamp = (int) ($parts['t'] ?? 0);
if (abs(time() - $timestamp) > $tolerance) {
return false;
}
$expected = hash_hmac('sha256', $timestamp . '.' . $body, $secret);
return hash_equals($expected, $parts['v1'] ?? '');
}
// $body = file_get_contents('php://input');
// ankora_signature_valid($secret, $body, $_SERVER['HTTP_ANKORA_SIGNATURE'] ?? '');require "openssl"
def ankora_signature_valid?(secret, body, header, tolerance: 300)
parts = header.to_s.split(",").filter_map { |part| part.split("=", 2) if part.include?("=") }.to_h
timestamp = parts["t"].to_i
return false if (Time.now.to_i - timestamp).abs > tolerance
expected = OpenSSL::HMAC.hexdigest("SHA256", secret, "#{timestamp}.#{body}")
Rack::Utils.secure_compare(expected, parts["v1"].to_s)
endОтвет, повторы и дубли
- Ответьте любым кодом 2xx в течение 10 секунд. Тяжёлую обработку делайте в фоне после ответа.
- Другой код, ошибка соединения или долгий ответ — отказ. Повторы: через 1 минуту, 5 минут, 30 минут, 2 часа, 6, 12 и 24 часа. Редиректы не повторяются.
- Одно событие может прийти дважды — например, ваш сервер принял его, но ответ потерялся. Отсекайте дубли по
Ankora-Event-Id: он одинаковый во всех повторах. - События могут прийти не в том порядке, в каком случились: сверяйтесь с
created_atи id операций. - Если адрес трое суток не принимает ничего, подписка выключается, а владельцу бизнеса уходит письмо. Включить её снова можно в кабинете.
Проверить адрес и проверку подписи — кнопкой «Отправить тестовое событие» в кабинете или POST /webhooks/{id}/test: придёт событие webhook.test, а журнал последних доставок с кодами ответа — в GET /webhooks/{id}.
Сценарии с кодом
Касса: продажа со списанием бонусов и возврат
- Кассир сканирует QR с карты клиента — найдите карту: GET /cards/lookup?card_number=….
- Покажите, сколько можно списать и сколько начислится: POST /cards/{id}/checkout/preview. Скидка по ступени клиента уже посчитана.
- Клиент согласился — проведите продажу: POST /cards/{id}/checkout с номером чека. Повтор с тем же номером не проведёт её дважды.
- Чек вернули — POST /purchases/{external_id}/refund: начисленное снимется, списанные бонусы вернутся.
const API = "https://ankora.pro/api/v2/public";
const headers = { Authorization: "Bearer ak_ВАШ_КЛЮЧ", "Content-Type": "application/json" };
async function call(method, path, body, idempotencyKey) {
const response = await fetch(API + path, {
method,
headers: idempotencyKey ? { ...headers, "Idempotency-Key": idempotencyKey } : headers,
body: body && JSON.stringify(body),
});
const json = await response.json();
if (!response.ok) throw Object.assign(new Error(json.message), { code: json.error, details: json.details });
return json;
}
const { card } = await call("GET", `/cards/lookup?card_number=${encodeURIComponent(qrValue)}`);
const preview = await call("POST", `/cards/${card.id}/checkout/preview`, { amount: 1500, redeem_cashback: 100 });
// preview.to_pay — к оплате деньгами, preview.cashback.earn — сколько начислится
const sale = await call("POST", `/cards/${card.id}/checkout`,
{ amount: 1500, redeem_cashback: 100, external_id: receiptNumber, location_id: 3 }, crypto.randomUUID());
// sale.receipt.paid, sale.receipt.earned_cashback, sale.card.cashback_balance1С: начисление за чек и баланс клиента
Функция АнкораЗапрос(Метод, Путь, Тело = Неопределено, КлючПовтора = "") Экспорт
Соединение = Новый HTTPСоединение("ankora.pro", 443, , , , 30, Новый ЗащищенноеСоединениеOpenSSL());
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Bearer " + Константы.КлючАнкоры.Получить());
Заголовки.Вставить("Content-Type", "application/json");
Если ЗначениеЗаполнено(КлючПовтора) Тогда
Заголовки.Вставить("Idempotency-Key", КлючПовтора);
КонецЕсли;
Запрос = Новый HTTPЗапрос("/api/v2/public" + Путь, Заголовки);
Если Тело <> Неопределено Тогда
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, Тело);
Запрос.УстановитьТелоИзСтроки(Запись.Закрыть(), КодировкаТекста.UTF8);
КонецЕсли;
Ответ = Соединение.ВызватьHTTPМетод(Метод, Запрос);
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
Результат = Новый Структура("Код, Данные", Ответ.КодСостояния, ПрочитатьJSON(Чтение, Истина));
Чтение.Закрыть();
Возврат Результат;
КонецФункции
// Начислить за чек: номер документа — защита от двойного начисления.
Тело = Новый Структура("phone, amount, external_id", Телефон, СуммаЧека, Документ.Номер);
Результат = АнкораЗапрос("POST", "/purchases", Тело);
Если Результат.Код >= 400 Тогда
// Результат.Данные["error"] — код ошибки, Результат.Данные["message"] — текст
ЗаписьЖурналаРегистрации("Анкора", УровеньЖурналаРегистрации.Ошибка, , , Результат.Данные["message"]);
КонецЕсли;
// Баланс клиента по телефону.
Результат = АнкораЗапрос("GET", "/cards/lookup?phone=" + КодироватьСтроку(Телефон, СпособКодированияСтроки.КодировкаURL));
Если Результат.Код = 200 Тогда
Кэшбэк = Результат.Данные["card"]["cashback_balance"];
КонецЕсли;Синхронизация с CRM
- Один раз выгрузите всех клиентов — постранично через
after_id. - Подпишитесь на
card.created,customer.updatedиtransaction.created— новые клиенты и движения балансов придут сами. - Изменения из CRM отправляйте в Анкору: профиль — PATCH /customers/{id}, бонусы за сделку — POST /purchases с номером сделки как
external_id.
Zapier, Make и другие no-code сервисы
Подключите модуль HTTP-запроса с заголовком Authorization: Bearer ak_…. Для мгновенного триггера подпишитесь через POST /webhooks на адрес, который выдаст сервис, а при отключении сценария отпишитесь через DELETE /webhooks/{id}. Для триггера по расписанию — GET /transactions или GET /customers с after_id.
Справочники
Аккаунт, точки продажи, программы лояльности со всеми настройками механик, акции.
Спецификация OpenAPI
GET
/openapi.json
без ключа
Эта документация в формате OpenAPI 3.1 — для импорта в Postman или Insomnia, генерации клиента и чтения ИИ-агентами. Ключ не нужен.
Пример запроса
curl https://ankora.pro/api/v2/public/openapi.jsonОтветы
200 Спецификация.
{
"openapi": "3.1.0",
"info": {
"title": "API Анкоры",
"version": "2.0"
},
"paths": {
}
}Ещё: 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Аккаунт и состояние ключа
GET
/account
Бизнес, которому принадлежит ключ, его подписка и разрешены ли сейчас операции. Удобно как первый запрос интеграции: проверить ключ и понять, почему операции могут отклоняться.
Пример запроса
curl https://ankora.pro/api/v2/public/account \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Аккаунт.
{
"business": {
"id": 42,
"name": "Кофейня «Зерно»",
"slug": "zerno",
"timezone": "Europe/Moscow"
},
"subscription": {
"status": "active",
"plan": "Бизнес",
"active_until": "2026-11-20T00:00:00+03:00",
"trial_ends_at": null
},
"api": {
"operations_allowed": true,
"blocked_reason": null,
"rate_limit_per_minute": 120,
"permissions": {
"balance_management": false,
"refunds": true
}
}
}Ещё: 401, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Точки продажи
GET
/locations
Точки бизнеса. Их id передают в location_id операций, чтобы покупки и списания попали в аналитику по точкам.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
limit |
строка запроса | integer | Сколько записей на странице, от 1 до 100. |
after_id |
строка запроса | integer | Вернуть записи с id больше этого — значение next_after_id из предыдущей страницы. |
Пример запроса
curl https://ankora.pro/api/v2/public/locations \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Страница точек.
{
"data": [
{
"id": 3,
"name": "Кофейня на Тверской",
"address": "Москва, Тверская, 1",
"latitude": 55.7576,
"longitude": 37.6136,
"radius_meters": 100,
"nearby_message": "Мы рядом — заходите за кофе",
"active": true,
"geo_program_ids": [
7
],
"created_at": "2026-03-02T10:00:00+03:00",
"updated_at": "2026-09-12T18:20:00+03:00"
}
],
"has_more": false,
"next_after_id": 3
}Ещё: 401, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Точка продажи
GET
/locations/{id}
Одна точка бизнеса.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Пример запроса
curl https://ankora.pro/api/v2/public/locations/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Точка.
{
"location": {
"id": 3,
"name": "Кофейня на Тверской",
"address": "Москва, Тверская, 1",
"latitude": 55.7576,
"longitude": 37.6136,
"radius_meters": 100,
"nearby_message": "Мы рядом — заходите за кофе",
"active": true,
"geo_program_ids": [
7
],
"created_at": "2026-03-02T10:00:00+03:00",
"updated_at": "2026-09-12T18:20:00+03:00"
}
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Программы лояльности
GET
/programs
Все программы бизнеса, включая выключенные, со всеми настройками механик.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
limit |
строка запроса | integer | Сколько записей на странице, от 1 до 100. |
after_id |
строка запроса | integer | Вернуть записи с id больше этого — значение next_after_id из предыдущей страницы. |
Пример запроса
curl https://ankora.pro/api/v2/public/programs \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Страница программ.
{
"data": [
{
"id": 7,
"name": "Кофейня",
"active": true,
"cashback": {
"enabled": true,
"percent": 3.0,
"tiers": [
{
"threshold": 10000.0,
"percent": 5.0,
"name": "Серебро",
"color": "#9ca3af"
},
{
"threshold": 30000.0,
"percent": 7.0,
"name": "Золото",
"color": null
}
],
"auto_award": true,
"max_balance": 5000.0,
"max_redemption_percent": 30.0,
"expiry": {
"enabled": true,
"days": 90,
"policy": "from_earn",
"fixed_date": null
},
"description": null
},
"points": {
"enabled": false,
"percent": 5.0,
"tiers": [
],
"auto_award": true,
"currency_name": "баллы",
"redemption_rate": 1.0,
"max_balance": null,
"max_redemption_percent": 100.0,
"expiry": {
"enabled": false,
"days": null,
"policy": "from_earn",
"fixed_date": null
},
"description": null
},
"stamps": {
"enabled": true,
"target": 6,
"reward_description": "Капучино в подарок",
"auto_reset": true,
"expiry": {
"enabled": false,
"days": null,
"mode": "per_stamp"
},
"description": null
},
"discount": {
"enabled": false,
"percent": 0.0,
"tiers": [
],
"description": null
},
"tier_windows": {
"spend_months": 12,
"visits_months": null,
"drop_reminder": {
"enabled": true,
"days": 7
}
},
"guest_status": {
"enabled": false,
"counting_mode": "manual",
"tiers": [
],
"description": null
},
"welcome_bonus": {
"enabled": true,
"type": "cashback",
"amount": 200.0,
"expiry_days": 30,
"delay_hours": 0,
"after_first_purchase": false,
"message": null
},
"birthday_bonus": {
"enabled": true,
"gift": true,
"type": "cashback",
"amount": 300.0,
"days_before": 3,
"expiry_days": 14,
"message": null,
"greeting_message": null
},
"referral": {
"enabled": true,
"type": "cashback",
"recipients": "both",
"referee_amount": 100.0,
"referrer_amount": 150.0,
"message": null
},
"expiry_reminders": {
"enabled": true,
"days": [
7,
1
],
"message": "Напоминаем: {amount} бонусов сгорит через {days} дн. Успейте воспользоваться!"
},
"visit_passes": {
"enabled": false,
"default_expiry_days": null,
"grant_cashback": true,
"notify_exhausted": true
},
"memberships": {
"enabled": true,
"expiry_reminder_days": 3,
"plans": [
{
"id": 11,
"name": "Безлимит на месяц",
"description": null,
"duration_days": 30,
"suggested_sale_price": 3500.0,
"suggested_renewal_price": 3000.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"actions": [
{
"id": 21,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1
}
]
}
]
},
"registration_fields": [
{
"key": "phone",
"label": "Телефон",
"type": "phone",
"required": true
},
{
"key": "name",
"label": "Имя",
"type": "text",
"required": true
}
],
"created_at": "2026-03-02T10:00:00+03:00",
"updated_at": "2026-10-01T09:00:00+03:00"
}
],
"has_more": false,
"next_after_id": 7
}Ещё: 401, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Программа лояльности
GET
/programs/{id}
Все настройки механик программы так, как их задал владелец в кабинете: кэшбэк, баллы и скидка со ступенями, штампы, сгорание, приветственный бонус, бонус ко дню рождения, рефералка, статусы гостя, абонементы и шаблоны подписок, поля анкеты.
Действующий для конкретного клиента процент (с учётом его ступени) приходит в карте — card.tier.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Пример запроса
curl https://ankora.pro/api/v2/public/programs/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Программа.
{
"program": {
"id": 7,
"name": "Кофейня",
"active": true,
"cashback": {
"enabled": true,
"percent": 3.0,
"tiers": [
{
"threshold": 10000.0,
"percent": 5.0,
"name": "Серебро",
"color": "#9ca3af"
},
{
"threshold": 30000.0,
"percent": 7.0,
"name": "Золото",
"color": null
}
],
"auto_award": true,
"max_balance": 5000.0,
"max_redemption_percent": 30.0,
"expiry": {
"enabled": true,
"days": 90,
"policy": "from_earn",
"fixed_date": null
},
"description": null
},
"points": {
"enabled": false,
"percent": 5.0,
"tiers": [
],
"auto_award": true,
"currency_name": "баллы",
"redemption_rate": 1.0,
"max_balance": null,
"max_redemption_percent": 100.0,
"expiry": {
"enabled": false,
"days": null,
"policy": "from_earn",
"fixed_date": null
},
"description": null
},
"stamps": {
"enabled": true,
"target": 6,
"reward_description": "Капучино в подарок",
"auto_reset": true,
"expiry": {
"enabled": false,
"days": null,
"mode": "per_stamp"
},
"description": null
},
"discount": {
"enabled": false,
"percent": 0.0,
"tiers": [
],
"description": null
},
"tier_windows": {
"spend_months": 12,
"visits_months": null,
"drop_reminder": {
"enabled": true,
"days": 7
}
},
"guest_status": {
"enabled": false,
"counting_mode": "manual",
"tiers": [
],
"description": null
},
"welcome_bonus": {
"enabled": true,
"type": "cashback",
"amount": 200.0,
"expiry_days": 30,
"delay_hours": 0,
"after_first_purchase": false,
"message": null
},
"birthday_bonus": {
"enabled": true,
"gift": true,
"type": "cashback",
"amount": 300.0,
"days_before": 3,
"expiry_days": 14,
"message": null,
"greeting_message": null
},
"referral": {
"enabled": true,
"type": "cashback",
"recipients": "both",
"referee_amount": 100.0,
"referrer_amount": 150.0,
"message": null
},
"expiry_reminders": {
"enabled": true,
"days": [
7,
1
],
"message": "Напоминаем: {amount} бонусов сгорит через {days} дн. Успейте воспользоваться!"
},
"visit_passes": {
"enabled": false,
"default_expiry_days": null,
"grant_cashback": true,
"notify_exhausted": true
},
"memberships": {
"enabled": true,
"expiry_reminder_days": 3,
"plans": [
{
"id": 11,
"name": "Безлимит на месяц",
"description": null,
"duration_days": 30,
"suggested_sale_price": 3500.0,
"suggested_renewal_price": 3000.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"actions": [
{
"id": 21,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1
}
]
}
]
},
"registration_fields": [
{
"key": "phone",
"label": "Телефон",
"type": "phone",
"required": true
},
{
"key": "name",
"label": "Имя",
"type": "text",
"required": true
}
],
"created_at": "2026-03-02T10:00:00+03:00",
"updated_at": "2026-10-01T09:00:00+03:00"
}
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Акции
GET
/promotions
Акции бизнеса: подарочный бонус сегменту клиентов (bonus) или множитель начисления на период (multiplier, например «двойные штампы»). Множитель идущей акции Анкора применяет сама — при начислении за покупку и при начислении штампов.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
limit |
строка запроса | integer | Сколько записей на странице, от 1 до 100. |
after_id |
строка запроса | integer | Вернуть записи с id больше этого — значение next_after_id из предыдущей страницы. |
state |
строка запроса | string | Статус акции; несколько — через запятую. |
program_id |
строка запроса | integer |
Пример запроса
curl https://ankora.pro/api/v2/public/promotions \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Страница акций.
{
"data": [
{
"id": 31,
"program_id": 7,
"name": "Двойные штампы до конца октября",
"kind": "multiplier",
"state": "active",
"starts_at": "2026-10-20T00:00:00+03:00",
"ends_at": "2026-10-31T23:59:59+03:00",
"bonus": null,
"multiplier": {
"value": 2.0,
"targets": [
"stamps"
]
},
"message": "Двойные штампы до 31 октября",
"card_text": "Двойные штампы до 31.10",
"control_group_percent": 20,
"cards_count": 480,
"control_count": 120,
"launched_at": "2026-10-20T00:00:05+03:00",
"finished_at": null,
"cancelled_at": null,
"created_at": "2026-10-18T15:00:00+03:00"
}
],
"has_more": false,
"next_after_id": 31
}Ещё: 401, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Клиенты
База клиентов, профили и карты.
Список клиентов
GET
/customers
Все клиенты бизнеса, у которых есть карта, страницами по возрастанию id. В каждой записи — профиль и все карты клиента с балансами.
Чтобы выгрузить всю базу, повторяйте запрос с after_id из next_after_id, пока has_more не станет false. Для регулярной синхронизации добавьте updated_since: клиент попадёт в выборку, если изменился его профиль или любая из карт, включая баланс.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
limit |
строка запроса | integer | Сколько записей на странице, от 1 до 100. |
after_id |
строка запроса | integer | Вернуть записи с id больше этого — значение next_after_id из предыдущей страницы. |
since_id |
строка запроса | integer | Старое имя after_id, работает так же. |
phone |
строка запроса | string | Телефон в любом российском формате. |
email |
строка запроса | string | Email, без учёта регистра. |
card_number |
строка запроса | string | Номер карты, без учёта регистра и пробелов. |
program_id |
строка запроса | integer | Только клиенты с картой в этой программе. В записи всё равно приходят все карты клиента. |
segment |
строка запроса | RfmSegment | RFM-сегмент карты. |
created_since |
строка запроса | string | Клиент зарегистрирован не раньше этого момента. Дата 2026-10-01 или время ISO 8601; без смещения — в часовом поясе бизнеса. |
updated_since |
строка запроса | string | Профиль клиента или любая его карта изменились не раньше этого момента. Формат — как у created_since. |
Пример запроса
curl https://ankora.pro/api/v2/public/customers \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Страница клиентов.
{
"data": [
{
"id": 456,
"name": "Анна",
"phone": "+79991234567",
"email": "anna@example.ru",
"birthday": "1990-05-17",
"gender": null,
"custom_fields": {
},
"consent_accepted_at": "2026-03-02T10:15:00+03:00",
"marketing_consent": true,
"marketing_consent_at": "2026-03-02T10:15:00+03:00",
"marketing_unsubscribed_at": null,
"telegram_linked": false,
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"cards": [
{
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00"
}
]
}
],
"has_more": true,
"next_after_id": 457
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Найти или создать клиента
POST
/customers
Заводит клиента и карту в программе program_id (по умолчанию — в первой активной) и возвращает created. Если клиент с таким телефоном или email уже есть с картой в этой программе — возвращает его со статусом exists; если есть, но без карты в ней — заводит карту ему же.
Клиент создаётся с согласием на обработку персональных данных: его собирает ваша система. Согласие на рекламные рассылки — только если передан marketing_consent: true. Приветственный бонус начисляется по правилам программы.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
phone |
string | null | Телефон в любом российском формате. |
email |
string | null | |
name |
string | null | |
birthday |
string | null | |
gender |
string | null |
Значения: male, female, other
|
custom_fields |
object |
Поля анкеты сверх стандартных — ключи из registration_fields программы. При правке сливаются с записанными; пустое значение удаляет поле.
|
program_id |
integer | Программа |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
marketing_consent |
boolean | Клиент дал согласие на рекламные рассылки. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/customers \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"phone":"+79991234567","name":"Анна","email":"anna@example.ru","birthday":"1990-05-17","gender":"female","custom_fields":{"car":"Kia Rio"}}'Ответы
200 Клиент уже есть с картой в этой программе — вернули его.
{
"status": "exists",
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"customer": {
"id": 456,
"name": "Анна",
"phone": "+79991234567",
"email": "anna@example.ru",
"birthday": "1990-05-17",
"gender": null,
"custom_fields": {
},
"consent_accepted_at": "2026-03-02T10:15:00+03:00",
"marketing_consent": true,
"marketing_consent_at": "2026-03-02T10:15:00+03:00",
"marketing_unsubscribed_at": null,
"telegram_linked": false,
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"cards": [
{
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
]
}
}201 Клиент и карта созданы.
{
"status": "created",
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"customer": {
"id": 456,
"name": "Анна",
"phone": "+79991234567",
"email": "anna@example.ru",
"birthday": "1990-05-17",
"gender": null,
"custom_fields": {
},
"consent_accepted_at": "2026-03-02T10:15:00+03:00",
"marketing_consent": true,
"marketing_consent_at": "2026-03-02T10:15:00+03:00",
"marketing_unsubscribed_at": null,
"telegram_linked": false,
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"cards": [
{
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
]
}
}422 Не передан телефон или клиента нельзя создать.
Нет ни телефона, ни email
{
"error": "parameter_missing",
"message": "Передайте один из параметров: phone, email",
"details": {
"params": [
"phone",
"email"
]
}
}Поля нет в анкете программы
{
"error": "parameter_invalid",
"message": "Неизвестные поля анкеты: pet. Допустимы: car",
"details": {
"param": "custom_fields"
}
}Отказ по правилам Анкоры
{
"error": "operation_rejected",
"message": "Достигнут лимит карт вашего тарифа"
}Ещё: 400, 401, 403, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Найти карту клиента
GET
/customers/search
Карта клиента с балансами по любому идентификатору: телефону, номеру карты (например, с QR на кассе), id карты или клиента, id клиента во внешней системе.
Если у клиента карты в нескольких программах и program_id не передан, вернётся карта первой активной программы.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
card_id |
строка запроса | integer | |
card_number |
строка запроса | string | Номер карты, без учёта регистра и пробелов. |
customer_id |
строка запроса | integer | |
phone |
строка запроса | string | Телефон в любом российском формате. |
external_customer_id |
строка запроса | string | Id клиента в вашей системе — если вы уже передавали его вместе с телефоном. |
program_id |
строка запроса | integer | Программа лояльности, если у клиента карты в нескольких. |
Пример запроса
curl https://ankora.pro/api/v2/public/customers/search \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Карта найдена.
{
"found": true,
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Профиль клиента
GET
/customers/{id}
Всё о клиенте — контакты, день рождения, поля анкеты, согласия — и все его карты целиком.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Пример запроса
curl https://ankora.pro/api/v2/public/customers/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Профиль.
{
"customer": {
"id": 456,
"name": "Анна",
"phone": "+79991234567",
"email": "anna@example.ru",
"birthday": "1990-05-17",
"gender": null,
"custom_fields": {
},
"consent_accepted_at": "2026-03-02T10:15:00+03:00",
"marketing_consent": true,
"marketing_consent_at": "2026-03-02T10:15:00+03:00",
"marketing_unsubscribed_at": null,
"telegram_linked": false,
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"cards": [
{
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
]
}
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Изменить профиль клиента
PATCH
/customers/{id}
Меняет только переданные поля. Телефон и email, которые уже у другого клиента бизнеса, не принимаются — иначе карты двух людей склеятся. Изменения попадают в журнал действий кабинета.
Согласие на рекламные рассылки через API можно только отозвать (marketing_consent: false), дать его клиент должен сам — на карте или в форме регистрации.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
phone |
string | null | Телефон в любом российском формате. |
email |
string | null | |
name |
string | null | |
birthday |
string | null | |
gender |
string | null |
Значения: male, female, other
|
custom_fields |
object |
Поля анкеты сверх стандартных — ключи из registration_fields программы. При правке сливаются с записанными; пустое значение удаляет поле.
|
marketing_consent |
boolean |
Отзыв согласия на рекламу.
Значения: false
|
Пример запроса
curl -X PATCH https://ankora.pro/api/v2/public/customers/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"birthday":"1990-05-17","custom_fields":{"car":"Kia Rio"}}'Ответы
200 Профиль обновлён.
{
"customer": {
"id": 456,
"name": "Анна",
"phone": "+79991234567",
"email": "anna@example.ru",
"birthday": "1990-05-17",
"gender": null,
"custom_fields": {
},
"consent_accepted_at": "2026-03-02T10:15:00+03:00",
"marketing_consent": true,
"marketing_consent_at": "2026-03-02T10:15:00+03:00",
"marketing_unsubscribed_at": null,
"telegram_linked": false,
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"cards": [
{
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
]
}
}422 Ошибка в полях, телефон или email заняты, согласие на рекламу нельзя дать.
{
"error": "operation_rejected",
"message": "Телефон +79991234567 уже у другого клиента (id 457)",
"details": {
"field": "phone",
"customer_id": 457
}
}{
"error": "parameter_invalid",
"message": "Согласие на рекламу клиент даёт сам — на карте или в форме регистрации; через API его можно только отозвать",
"details": {
"param": "marketing_consent"
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Найти карту
GET
/cards/lookup
Карта по любому идентификатору: телефону, номеру карты, id клиента или id клиента в вашей системе. Если у клиента карты в нескольких программах, передайте program_id — иначе ответ program_required со списком программ.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
card_number |
строка запроса | string | Номер карты, без учёта регистра и пробелов. |
customer_id |
строка запроса | integer | |
phone |
строка запроса | string | Телефон в любом российском формате. |
external_customer_id |
строка запроса | string | Id клиента в вашей системе — если вы уже передавали его вместе с телефоном. |
program_id |
строка запроса | integer | Программа лояльности, если у клиента карты в нескольких. |
Пример запроса
curl https://ankora.pro/api/v2/public/cards/lookup \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Карта.
{
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
}422 Не передан идентификатор или нужна программа.
Карты в нескольких программах
{
"error": "program_required",
"message": "У клиента карты в нескольких программах — передайте program_id",
"details": {
"program_ids": [
7,
9
]
}
}Нет идентификатора
{
"error": "parameter_missing",
"message": "Передайте один из параметров: card_id, card_number, customer_id, phone, external_customer_id",
"details": {
"params": [
"card_id",
"card_number",
"customer_id",
"phone",
"external_customer_id"
]
}
}Ещё: 401, 404, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Карта
GET
/cards/{id}
Карта целиком — балансы, ступень, ближайшее сгорание, абонементы, подписка, Wallet.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Пример запроса
curl https://ankora.pro/api/v2/public/cards/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Карта.
{
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Покупки и бонусы
Начисление за покупку и списание кэшбэка и баллов.
Рассчитать продажу
POST
/cards/{id}/checkout/preview
Расчёт продажи без записи — то же, что покажет касса Анкоры: скидка по ступени клиента, сколько бонусов можно списать по этому чеку, сколько начислится с оплаченной суммы и сколько клиент платит деньгами. Ошибки — те же, что вернёт POST /cards/{id}/checkout, поэтому расчёт заодно проверяет списание.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
amountобяз. |
number | string | Сумма чека до скидки, ₽. |
redeem_cashback |
number | string |
Сколько кэшбэка списать в оплату, ₽ — не больше max_redeemable из расчёта.
|
redeem_points |
number | string | Сколько баллов списать в оплату. |
cashback_to_add |
number | string |
Ручной режим кэшбэка: сколько начислить — не больше max_manual_award.
|
points_to_add |
number | string |
Ручной режим баллов: сколько начислить — не больше max_manual_award.
|
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/checkout/preview \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"amount":1000,"redeem_cashback":100}'Ответы
200 Расчёт.
{
"amount": 1000.0,
"discount_percent": 10.0,
"discount_amount": 100.0,
"after_discount": 900.0,
"cashback": {
"enabled": true,
"available": 300.0,
"max_redeemable": 300.0,
"redeem": 100.0,
"earn_percent": 10.0,
"earn": 80.0,
"auto_award": true,
"max_manual_award": null
},
"points": {
"enabled": false,
"available": 0.0,
"max_redeemable": 0.0,
"redeem": 0.0,
"earn_percent": 0.0,
"earn": 0.0,
"auto_award": false,
"max_manual_award": null
},
"promotion_multipliers": {
"cashback": 1.0,
"points": 1.0
},
"to_pay": 800.0
}422 Не хватает баланса, превышен лимит списания или ошибка в параметрах.
Больше лимита списания программы
{
"error": "redemption_limit_exceeded",
"message": "Списание кэшбэка по этому чеку — не больше 500 (50% от суммы после скидки)",
"details": {
"currency": "cashback",
"max": 500.0,
"requested": 600.0
}
}Не хватает баланса
{
"error": "insufficient_balance",
"message": "Недостаточно кэшбэка: на карте 300 ₽, запрошено 400 ₽",
"details": {
"currency": "cashback",
"balance": 300.0,
"requested": 400.0
}
}Нет номера чека
{
"error": "parameter_missing",
"message": "Не передан параметр external_id",
"details": {
"param": "external_id"
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Провести продажу
POST
/cards/{id}/checkout
Продажа одним вызовом, как на кассе Анкоры: скидка по ступени → списание кэшбэка и баллов → покупка → начисление с суммы, оплаченной деньгами. Клиенту уходит одно уведомление.
external_id — номер чека: повтор с тем же номером вернёт skipped и не проведёт продажу второй раз, по нему же работает возврат POST /purchases/{external_id}/refund. Неудачная продажа номер не занимает.
Если программа в ручном режиме начисления, передайте cashback_to_add или points_to_add — не больше max_manual_award из расчёта.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
amountобяз. |
number | string | Сумма чека до скидки, ₽. |
redeem_cashback |
number | string |
Сколько кэшбэка списать в оплату, ₽ — не больше max_redeemable из расчёта.
|
redeem_points |
number | string | Сколько баллов списать в оплату. |
cashback_to_add |
number | string |
Ручной режим кэшбэка: сколько начислить — не больше max_manual_award.
|
points_to_add |
number | string |
Ручной режим баллов: сколько начислить — не больше max_manual_award.
|
external_idобяз. |
string | Номер чека в вашей системе. |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/checkout \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"amount":1000,"redeem_cashback":200,"external_id":"CHEK-2026-000125","location_id":3}'Ответы
200
Чек с этим external_id уже проведён.
{
"status": "skipped",
"reason": "already_processed"
}201 Продажа проведена.
{
"status": "completed",
"external_id": "CHEK-2026-000125",
"receipt": {
"amount": 1000.0,
"discount_amount": 0.0,
"after_discount": 1000.0,
"redeemed_cashback": 200.0,
"redeemed_points": 0.0,
"paid": 800.0,
"earned_cashback": 80.0,
"earned_points": 0.0
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9010,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "purchase_record",
"operation_label": "Покупка",
"mechanic": "purchase",
"direction": "neutral",
"amount": 1000.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": 1000.0,
"description": "Покупка на 1000 ₽",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
},
{
"id": 9011,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_spend",
"operation_label": "Списание кэшбека",
"mechanic": "cashback",
"direction": "debit",
"amount": 200.0,
"balance_before": 300.0,
"balance_after": 100.0,
"purchase_amount": null,
"description": "Списание кэшбека при покупке",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": 9010,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
},
{
"id": 9012,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_earn",
"operation_label": "Начисление кэшбека (за покупку)",
"mechanic": "cashback",
"direction": "credit",
"amount": 80.0,
"balance_before": 100.0,
"balance_after": 180.0,
"purchase_amount": 800.0,
"description": "Начисление кэшбека при покупке",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": 9010,
"expires_at": "2026-11-30T23:59:59+03:00",
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 Не хватает баланса, превышен лимит списания или ошибка в параметрах.
Больше лимита списания программы
{
"error": "redemption_limit_exceeded",
"message": "Списание кэшбэка по этому чеку — не больше 500 (50% от суммы после скидки)",
"details": {
"currency": "cashback",
"max": 500.0,
"requested": 600.0
}
}Не хватает баланса
{
"error": "insufficient_balance",
"message": "Недостаточно кэшбэка: на карте 300 ₽, запрошено 400 ₽",
"details": {
"currency": "cashback",
"balance": 300.0,
"requested": 400.0
}
}Нет номера чека
{
"error": "parameter_missing",
"message": "Не передан параметр external_id",
"details": {
"param": "external_id"
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Вернуть покупку
POST
/purchases/{external_id}/refund
Возврат по номеру чека — продажи (POST /cards/{id}/checkout), покупки (POST /purchases) или списания (POST /redemptions с external_id). Снимает ровно то, что начислила эта покупка (с той ступенью и множителем акции, что действовали тогда), возвращает бонусы, списанные по чеку, и уменьшает сумму покупок клиента. Баланс в минус не уходит. Уведомление клиенту не отправляется.
Возврат может быть частичным: передайте amount и свой refund_id для каждого документа возврата — вместе они не вернут больше, чем было по чеку. Без refund_id возврат один, на весь чек.
Нужно право ключа «Возвраты и отмены».
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
external_idобяз. |
путь | string | Номер чека, переданный при продаже или покупке. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
refund_id |
string | Номер документа возврата. |
amount |
number | string | Сумма возврата в деньгах чека; без неё — весь чек. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/purchases/CHEK-2026-000125/refund \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"refund_id":"VOZ-17","amount":400}'Ответы
200 Возврат проведён — или этот документ возврата уже проведён.
{
"status": "refunded",
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9020,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_spend",
"operation_label": "Списание кэшбека",
"mechanic": "cashback",
"direction": "debit",
"amount": 80.0,
"balance_before": 180.0,
"balance_after": 100.0,
"purchase_amount": null,
"description": "Возврат покупки №CHEK-2026-000125",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": 9010,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
},
{
"id": 9021,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "total_spent_decrease",
"operation_label": "Уменьшение суммы покупок",
"mechanic": "total_spent",
"direction": "debit",
"amount": 1000.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Возврат покупки №CHEK-2026-000125",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": 9010,
"expires_at": null,
"expired": false,
"customer_visible": false,
"created_at": "2026-10-24T12:30:00+03:00"
},
{
"id": 9022,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_add",
"operation_label": "Начисление кэшбека",
"mechanic": "cashback",
"direction": "credit",
"amount": 200.0,
"balance_before": 100.0,
"balance_after": 300.0,
"purchase_amount": null,
"description": "Возврат покупки №CHEK-2026-000125: бонусы возвращены",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": 9011,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}{
"status": "skipped",
"reason": "already_processed"
}403 Операция выключена в правах ключа, или подписка бизнеса истекла.
Нет права ключа
{
"error": "permission_denied",
"message": "Операция выключена в правах ключа: включите «Начисление вручную, установка и корректировка балансов, сумма покупок» в кабинете → Интеграции → «API и Zapier»",
"details": {
"permission": "balance_management"
}
}Подписка истекла
{
"error": "subscription_required",
"message": "Подписка бизнеса истекла — операция интеграции пропущена",
"details": {
"reason": "subscription_expired"
}
}404 Покупки с таким номером чека нет.
{
"error": "not_found",
"message": "Покупка с номером чека CHEK-1 не найдена",
"details": {
"resource": "purchase"
}
}Ещё: 400, 401, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Начислить вручную
POST
/cards/{id}/balance/add
Начисляет кэшбэк или баллы вне покупки — подарок, компенсация, бонус за отзыв. Можно задать свой срок сгорания и текст, который клиент увидит в истории карты. Клиенту уходит уведомление о начислении.
Это ручная операция владельца: правила программы и потолок накопления к ней не применяются. Нужно право ключа «Управление балансами».
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
currencyобяз. |
string |
Значения: cashback, points
|
amountобяз. |
number | string | Сколько начислить: рубли кэшбэка или баллы. |
expires_at |
string |
Когда сгорит начисленное: дата 2026-12-31 или время ISO 8601. Без него — бессрочно.
|
description |
string | Текст в истории карты. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/balance/add \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"currency":"cashback","amount":200,"expires_at":"2026-11-30","description":"Спасибо за отзыв"}'Ответы
201 Начислено.
{
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_add",
"operation_label": "Начисление кэшбека",
"mechanic": "cashback",
"direction": "credit",
"amount": 200.0,
"balance_before": 0.0,
"balance_after": 75.0,
"purchase_amount": null,
"description": "Спасибо за отзыв",
"location_id": null,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": "2026-11-30T23:59:59+03:00",
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}403 Операция выключена в правах ключа, или подписка бизнеса истекла.
Нет права ключа
{
"error": "permission_denied",
"message": "Операция выключена в правах ключа: включите «Начисление вручную, установка и корректировка балансов, сумма покупок» в кабинете → Интеграции → «API и Zapier»",
"details": {
"permission": "balance_management"
}
}Подписка истекла
{
"error": "subscription_required",
"message": "Подписка бизнеса истекла — операция интеграции пропущена",
"details": {
"reason": "subscription_expired"
}
}422 Механика выключена или ошибка в параметрах.
{
"error": "mechanic_disabled",
"message": "Баллы выключены в программе «Кофейня»",
"details": {
"mechanic": "points"
}
}{
"error": "parameter_invalid",
"message": "Параметр currency: неизвестное значение rubles. Допустимо: cashback, points",
"details": {
"param": "currency"
}
}Ещё: 400, 401, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Списать
POST
/cards/{id}/balance/spend
Списывает кэшбэк или баллы с карты, например когда вы применяете их как скидку у себя на кассе. Клиенту уходит уведомление о списании. Списать кэшбэк и баллы одним запросом можно через POST /redemptions или в продаже — POST /cards/{id}/checkout.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
currencyобяз. |
string |
Значения: cashback, points
|
amountобяз. |
number | string | Сколько списать: рубли кэшбэка или баллы. |
description |
string | Текст в истории карты. |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/balance/spend \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"currency":"points","amount":150,"location_id":3}'Ответы
200 Списано.
{
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "points_spend",
"operation_label": "Списание баллов",
"mechanic": "points",
"direction": "debit",
"amount": 150.0,
"balance_before": 300.0,
"balance_after": 150.0,
"purchase_amount": null,
"description": "Списание через API",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 Не хватает баланса или ошибка в параметрах.
{
"error": "insufficient_balance",
"message": "Недостаточно баллов: на карте 50, запрошено 150",
"details": {
"currency": "points",
"balance": 50.0,
"requested": 150.0
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Установить баланс
POST
/cards/{id}/balance/set
Ставит баланс кэшбэка или баллов ровно в заданное значение — например, при переносе клиентов из другой программы лояльности. В истории появляется строка на разницу. Срок сгорания применяется, только если баланс вырос.
Нужно право ключа «Управление балансами».
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
currencyобяз. |
string |
Значения: cashback, points
|
balanceобяз. |
number | string | Каким должен стать баланс. |
expires_at |
string | Срок сгорания добавленной части. |
description |
string |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/balance/set \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"currency":"points","balance":1240,"description":"Перенос из старой программы"}'Ответы
200
Баланс установлен. Если он уже был таким, transactions пуст.
{
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "points_set",
"operation_label": "Установка баланса баллов",
"mechanic": "points",
"direction": "credit",
"amount": 1240.0,
"balance_before": 0.0,
"balance_after": 1240.0,
"purchase_amount": null,
"description": "Перенос из старой программы",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}403 Операция выключена в правах ключа, или подписка бизнеса истекла.
Нет права ключа
{
"error": "permission_denied",
"message": "Операция выключена в правах ключа: включите «Начисление вручную, установка и корректировка балансов, сумма покупок» в кабинете → Интеграции → «API и Zapier»",
"details": {
"permission": "balance_management"
}
}Подписка истекла
{
"error": "subscription_required",
"message": "Подписка бизнеса истекла — операция интеграции пропущена",
"details": {
"reason": "subscription_expired"
}
}Ещё: 400, 401, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Скорректировать баланс
POST
/cards/{id}/balance/adjust
Прибавляет к балансу или отнимает от него delta: кэшбэк, баллы или штампы. Отнять больше, чем есть, нельзя — спишется остаток.
Нужно право ключа «Управление балансами».
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
currencyобяз. |
string |
Значения: cashback, points, stamps
|
deltaобяз. |
number | string | Изменение со знаком, не ноль. Для штампов — целое. |
description |
string |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/balance/adjust \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"currency":"cashback","delta":-50,"description":"Ошибочное начисление"}'Ответы
200 Скорректировано.
{
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_adjust",
"operation_label": "Корректировка кэшбека",
"mechanic": "cashback",
"direction": "debit",
"amount": 50.0,
"balance_before": 125.0,
"balance_after": 75.0,
"purchase_amount": null,
"description": "Ошибочное начисление",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}403 Операция выключена в правах ключа, или подписка бизнеса истекла.
Нет права ключа
{
"error": "permission_denied",
"message": "Операция выключена в правах ключа: включите «Начисление вручную, установка и корректировка балансов, сумма покупок» в кабинете → Интеграции → «API и Zapier»",
"details": {
"permission": "balance_management"
}
}Подписка истекла
{
"error": "subscription_required",
"message": "Подписка бизнеса истекла — операция интеграции пропущена",
"details": {
"reason": "subscription_expired"
}
}422 Уменьшать нечего или ошибка в параметрах.
{
"error": "insufficient_balance",
"message": "Уменьшать нечего: на карте 0",
"details": {
"currency": "stamps",
"balance": 0.0,
"requested": 1.0
}
}{
"error": "parameter_invalid",
"message": "Параметр delta не может быть нулём",
"details": {
"param": "delta"
}
}Ещё: 400, 401, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Изменить сумму покупок
PUT
/cards/{id}/total_spent
Ставит сумму покупок клиента, от которой считается ступень кэшбэка, баллов и скидки, — например, клиент принёс чеки со старой карты. Бонусы при этом не начисляются, клиент изменение в истории не видит.
Нужно право ключа «Управление балансами».
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
total_spentобяз. |
number | string | Какой должна стать сумма покупок, ₽. |
reason |
string | Причина — попадёт в журнал изменений. |
Пример запроса
curl -X PUT https://ankora.pro/api/v2/public/cards/123/total_spent \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"total_spent":15000,"reason":"Чеки со старой карты"}'Ответы
200 Сумма покупок изменена.
{
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "total_spent_increase",
"operation_label": "Увеличение суммы покупок",
"mechanic": "total_spent",
"direction": "credit",
"amount": 2500.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Чеки со старой карты",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": false,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}403 Операция выключена в правах ключа, или подписка бизнеса истекла.
Нет права ключа
{
"error": "permission_denied",
"message": "Операция выключена в правах ключа: включите «Начисление вручную, установка и корректировка балансов, сумма покупок» в кабинете → Интеграции → «API и Zapier»",
"details": {
"permission": "balance_management"
}
}Подписка истекла
{
"error": "subscription_required",
"message": "Подписка бизнеса истекла — операция интеграции пропущена",
"details": {
"reason": "subscription_expired"
}
}Ещё: 400, 401, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Начислить за покупку
POST
/purchases
Главный метод для кассы и 1С: на каждый чек передайте сумму покупки, Анкора сама начислит кэшбэк и баллы по правилам программы — с учётом ступени клиента, идущих акций и потолка накопления. Штампы за покупку не начисляются, для них есть POST /stamps.
external_id — номер чека или заказа в вашей системе. Повтор с тем же external_id не начислит второй раз и вернёт skipped с причиной already_processed, так что повторять запрос после сбоя сети безопасно.
Если клиент передан телефоном или внешним id и не найден, ответ — skipped со статусом 200: покупка человека не из программы — обычное событие для кассы. Если передан card_id, card_number или customer_id и такой карты нет — ошибка 404.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
card_id |
integer | Id карты в Анкоре. |
card_number |
string | Номер карты |
customer_id |
integer | Id клиента в Анкоре. |
phone |
string | Телефон в любом российском формате. |
external_customer_id |
string | Id клиента в вашей системе. |
program_id |
integer | Программа лояльности. |
external_idобяз. |
string | Номер чека или заказа в вашей системе — защита от двойного начисления. |
amountобяз. |
number | string | Сумма покупки, ₽. |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/purchases \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"phone":"+79991234567","external_id":"CHEK-2026-000123","amount":1500}'Ответы
200 Покупка принята, но ничего не начислено.
Чек уже обработан
{
"status": "skipped",
"reason": "already_processed"
}Клиента нет в программе
{
"status": "skipped",
"reason": "no_customer"
}201 Начислено.
{
"status": "applied",
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
}422 Ошибка в параметрах.
Нет номера чека
{
"error": "parameter_missing",
"message": "Не передан параметр external_id",
"details": {
"param": "external_id"
}
}Сумма не больше нуля
{
"error": "parameter_invalid",
"message": "Параметр amount должен быть больше нуля",
"details": {
"param": "amount"
}
}Карты в нескольких программах
{
"error": "program_required",
"message": "У клиента карты в нескольких программах — передайте program_id",
"details": {
"program_ids": [
7,
9
]
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Списать кэшбэк или баллы
POST
/redemptions
Списывает бонусы клиента, которые вы применяете как скидку у себя на кассе. Можно списать кэшбэк, баллы или и то и другое одним запросом.
Списание атомарно: если чего-то не хватает, не списывается ничего. Клиенту уходит одно уведомление о списании. Чтобы повтор запроса после сбоя сети не списал второй раз, передавайте заголовок Idempotency-Key.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
card_id |
integer | Id карты в Анкоре. |
card_number |
string | Номер карты |
customer_id |
integer | Id клиента в Анкоре. |
phone |
string | Телефон в любом российском формате. |
external_customer_id |
string | Id клиента в вашей системе. |
program_id |
integer | Программа лояльности. |
cashback_amount |
number | string | Сколько кэшбэка списать, ₽. |
points_amount |
number | string | Сколько баллов списать. |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
external_id |
string |
Номер чека. Повтор с тем же номером не спишет второй раз; возврат покупки с этим номером (POST /purchases/{external_id}/refund) вернёт списанное.
|
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/redemptions \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"phone":"+79991234567","cashback_amount":50}'Ответы
200
Списано — или чек с этим external_id уже обработан.
{
"status": "redeemed",
"redeemed": {
"cashback": 50.0
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
}Повтор того же чека
{
"status": "skipped",
"reason": "already_processed"
}422 Не хватает баланса или ошибка в параметрах. Ничего не списано.
Не хватает кэшбэка
{
"error": "insufficient_balance",
"message": "Недостаточно кэшбэка: на карте 25 ₽, запрошено 50 ₽",
"details": {
"currency": "cashback",
"balance": 25.0,
"requested": 50.0
}
}Не передана сумма
{
"error": "parameter_missing",
"message": "Передайте один из параметров: cashback_amount, points_amount",
"details": {
"params": [
"cashback_amount",
"points_amount"
]
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Штампы
Штампы и награды за них.
Начислить штампы на карту
POST
/cards/{id}/stamps
Добавляет штампы. Во время акции «двойные штампы» начисляется больше — фактическое число в count. Набралось на награду — она появится в card.rewards_available.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
count |
integer | |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/stamps \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"count":1,"location_id":3}'Ответы
201 Начислено.
{
"count": 1,
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "stamp_add",
"operation_label": "Добавление штампа",
"mechanic": "stamps",
"direction": "credit",
"amount": 1.0,
"balance_before": 2.0,
"balance_after": 3.0,
"purchase_amount": null,
"description": "Штамп",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 Штампы выключены или ошибка в параметрах.
{
"error": "mechanic_disabled",
"message": "Штампы выключены в программе «Кофейня»",
"details": {
"mechanic": "stamps"
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Снять штампы
POST
/cards/{id}/stamps/remove
Снимает ошибочно поставленные штампы. Если просят больше, чем есть, снимаются все — partial будет true.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
count |
integer | |
reason |
string | Текст в истории карты. |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/stamps/remove \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"count":1,"reason":"Ошибка кассира"}'Ответы
200 Сняты.
{
"removed": 1,
"partial": false,
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "stamp_adjust",
"operation_label": "Корректировка штампов",
"mechanic": "stamps",
"direction": "debit",
"amount": 1.0,
"balance_before": 4.0,
"balance_after": 3.0,
"purchase_amount": null,
"description": "Ошибка кассира",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 На карте нет штампов.
{
"error": "insufficient_balance",
"message": "На карте нет штампов для списания",
"details": {
"currency": "stamps",
"balance": 0,
"requested": 1
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Выдать награду
POST
/cards/{id}/rewards/redeem
Списывает одну доступную награду за штампы.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/rewards/redeem \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)"Ответы
200 Награда выдана.
{
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "reward_use",
"operation_label": "Использование награды",
"mechanic": "stamps",
"direction": "debit",
"amount": 1.0,
"balance_before": 1.0,
"balance_after": 0.0,
"purchase_amount": null,
"description": "Использована награда: Капучино в подарок",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 Нет доступной награды.
{
"error": "insufficient_balance",
"message": "Нет доступных наград: соберите 6 штампов",
"details": {
"currency": "rewards",
"balance": 0,
"requested": 1
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Начислить штампы
POST
/stamps
Добавляет штампы на карту. Когда штампов набирается на награду, у клиента появляется доступная награда (rewards_available). Во время акции «двойные штампы» начисляется больше запрошенного — фактическое число приходит в count.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
card_id |
integer | Id карты в Анкоре. |
card_number |
string | Номер карты |
customer_id |
integer | Id клиента в Анкоре. |
phone |
string | Телефон в любом российском формате. |
external_customer_id |
string | Id клиента в вашей системе. |
program_id |
integer | Программа лояльности. |
count |
integer | Сколько штампов начислить. |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/stamps \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"card_number":"AABBCCDD00000001"}'Ответы
201 Штампы начислены.
{
"status": "added",
"count": 1,
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
}422 Штампы выключены в программе или ошибка в параметрах.
Штампы выключены
{
"error": "mechanic_disabled",
"message": "Штампы выключены в программе «Кофейня»",
"details": {
"mechanic": "stamps"
}
}Неверное количество
{
"error": "parameter_invalid",
"message": "Параметр count должен быть не меньше 1",
"details": {
"param": "count"
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Выдать награду за штампы
POST
/stamp_redemptions
Списывает одну доступную награду (например, «Капучино в подарок»).
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
card_id |
integer | Id карты в Анкоре. |
card_number |
string | Номер карты |
customer_id |
integer | Id клиента в Анкоре. |
phone |
string | Телефон в любом российском формате. |
external_customer_id |
string | Id клиента в вашей системе. |
program_id |
integer | Программа лояльности. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/stamp_redemptions \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"card_id":123}'Ответы
200 Награда выдана.
{
"status": "redeemed",
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
}
}422 Нет доступной награды.
{
"error": "insufficient_balance",
"message": "Нет доступных наград: соберите 6 штампов",
"details": {
"currency": "rewards",
"balance": 0,
"requested": 1
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Абонементы
Пакеты визитов — продажа, визиты, заморозка, возврат.
Продать абонемент
POST
/cards/{id}/visit_passes
Продаёт абонемент — пакет визитов — на карту. Если в программе включено «Начислять кэшбэк за абонемент», за продажу начисляется кэшбэк, а сумма попадает в сумму покупок.
expires_at: не передан — срок по умолчанию из настроек программы; null — бессрочный; дата или время — свой срок.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
titleобяз. |
string | Название абонемента. |
total_visitsобяз. |
integer | Сколько визитов в абонементе. |
priceобяз. |
number | string | Цена абонемента, ₽. |
expires_at |
string | null | |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/visit_passes \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"title":"10 занятий","total_visits":10,"price":5000,"expires_at":"2026-12-31"}'Ответы
201 Абонемент продан.
{
"visit_pass": {
"id": 41,
"card_id": 123,
"title": "10 занятий",
"state": "active",
"total_visits": 10,
"used_visits": 0,
"remaining_visits": 10,
"price": 5000.0,
"expires_at": "2026-12-31T00:00:00+03:00",
"frozen_since": null,
"last_usage_id": null,
"created_at": "2026-10-24T12:00:00+03:00"
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "visit_pass_issue",
"operation_label": "Продажа абонемента",
"mechanic": "visit_pass",
"direction": "credit",
"amount": 10.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Продан абонемент: 10 занятий",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 Абонементы выключены или ошибка в параметрах.
{
"error": "mechanic_disabled",
"message": "Абонементы выключены в программе «Кофейня»",
"details": {
"mechanic": "visit_passes"
}
}{
"error": "parameter_missing",
"message": "Не передан параметр total_visits",
"details": {
"param": "total_visits"
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Абонемент
GET
/visit_passes/{id}
Абонемент с историей визитов.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Пример запроса
curl https://ankora.pro/api/v2/public/visit_passes/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Абонемент.
{
"visit_pass": {
"id": 41,
"card_id": 123,
"title": "10 занятий",
"state": "active",
"total_visits": 10,
"used_visits": 1,
"remaining_visits": 9,
"price": 5000.0,
"expires_at": "2026-12-31T00:00:00+03:00",
"frozen_since": null,
"last_usage_id": 77,
"created_at": "2026-10-24T12:00:00+03:00"
},
"usages": [
{
"id": 77,
"used_at": "2026-10-24T18:00:00+03:00",
"reversed": false,
"reversed_at": null
}
]
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Засчитать визит
POST
/visit_passes/{id}/use
Списывает один визит. Последний визит закрывает абонемент (state = exhausted). Замороженный, истёкший и исчерпанный абонемент визит не принимает.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/visit_passes/123/use \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"location_id":3}'Ответы
200 Визит засчитан.
{
"visit_pass": {
"id": 41,
"card_id": 123,
"title": "10 занятий",
"state": "active",
"total_visits": 10,
"used_visits": 1,
"remaining_visits": 9,
"price": 5000.0,
"expires_at": "2026-12-31T00:00:00+03:00",
"frozen_since": null,
"last_usage_id": 77,
"created_at": "2026-10-24T12:00:00+03:00"
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "visit_pass_use",
"operation_label": "Списан визит абонемента",
"mechanic": "visit_pass",
"direction": "debit",
"amount": 1.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Списан визит: 10 занятий",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Отменить визит
POST
/visit_pass_usages/{id}/reverse
Возвращает ошибочно списанный визит на абонемент.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
reason |
string |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/visit_pass_usages/123/reverse \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"reason":"Отметили по ошибке"}'Ответы
200 Визит отменён.
{
"visit_pass": {
"id": 41,
"card_id": 123,
"title": "10 занятий",
"state": "active",
"total_visits": 10,
"used_visits": 0,
"remaining_visits": 10,
"price": 5000.0,
"expires_at": "2026-12-31T00:00:00+03:00",
"frozen_since": null,
"last_usage_id": null,
"created_at": "2026-10-24T12:00:00+03:00"
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "visit_pass_reverse",
"operation_label": "Отмена визита абонемента",
"mechanic": "visit_pass",
"direction": "credit",
"amount": 1.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Визит восстановлен: 10 занятий",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Заморозить абонемент
POST
/visit_passes/{id}/freeze
Ставит абонемент на паузу — например, клиент уехал в отпуск. Пока абонемент заморожен, визиты не списываются.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
reason |
string |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/visit_passes/123/freeze \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"reason":"Отпуск"}'Ответы
200 Заморожен.
{
"visit_pass": {
"id": 41,
"card_id": 123,
"title": "10 занятий",
"state": "frozen",
"total_visits": 10,
"used_visits": 1,
"remaining_visits": 9,
"price": 5000.0,
"expires_at": "2026-12-31T00:00:00+03:00",
"frozen_since": "2026-10-24T12:00:00+03:00",
"last_usage_id": 77,
"created_at": "2026-10-24T12:00:00+03:00"
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
]
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Разморозить абонемент
POST
/visit_passes/{id}/unfreeze
Снимает заморозку.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/visit_passes/123/unfreeze \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)"Ответы
200 Разморожен.
{
"visit_pass": {
"id": 41,
"card_id": 123,
"title": "10 занятий",
"state": "active",
"total_visits": 10,
"used_visits": 1,
"remaining_visits": 9,
"price": 5000.0,
"expires_at": "2026-12-31T00:00:00+03:00",
"frozen_since": null,
"last_usage_id": 77,
"created_at": "2026-10-24T12:00:00+03:00"
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
]
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Рассчитать возврат абонемента
GET
/visit_passes/{id}/refund_preview
Сколько денег вернуть за неиспользованные визиты — без записи.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
partial_amount |
строка запроса | number | Своя сумма возврата вместо расчётной. |
Пример запроса
curl https://ankora.pro/api/v2/public/visit_passes/123/refund_preview \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Расчёт.
{
"visit_pass_id": 41,
"refund_amount": 4500.0,
"remaining_visits": 9,
"total_visits": 10
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Вернуть абонемент
POST
/visit_passes/{id}/refund
Закрывает абонемент с возвратом денег за неиспользованные визиты (state = refunded). Деньги возвращаете вы — Анкора фиксирует возврат и сумму. Нужно право ключа «Возвраты и отмены».
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
partial_amount |
number | string | Своя сумма возврата вместо расчётной, ₽. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/visit_passes/123/refund \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"partial_amount":4000}'Ответы
200 Абонемент возвращён.
{
"visit_pass": {
"id": 41,
"card_id": 123,
"title": "10 занятий",
"state": "refunded",
"total_visits": 10,
"used_visits": 1,
"remaining_visits": 9,
"price": 5000.0,
"expires_at": "2026-12-31T00:00:00+03:00",
"frozen_since": null,
"last_usage_id": 77,
"created_at": "2026-10-24T12:00:00+03:00"
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "visit_pass_refund",
"operation_label": "Возврат за абонемент",
"mechanic": "visit_pass",
"direction": "debit",
"amount": 4500.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Возврат абонемента: 10 занятий",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}403 Операция выключена в правах ключа, или подписка бизнеса истекла.
Нет права ключа
{
"error": "permission_denied",
"message": "Операция выключена в правах ключа: включите «Начисление вручную, установка и корректировка балансов, сумма покупок» в кабинете → Интеграции → «API и Zapier»",
"details": {
"permission": "balance_management"
}
}Подписка истекла
{
"error": "subscription_required",
"message": "Подписка бизнеса истекла — операция интеграции пропущена",
"details": {
"reason": "subscription_expired"
}
}Ещё: 400, 401, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Подписки
Подписки клиентов с лимитами действий.
Продать подписку
POST
/cards/{id}/memberships
Продаёт подписку по шаблону программы (шаблоны — в GET /programs/{id}, memberships.plans). У клиента может быть одна действующая подписка.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
plan_idобяз. |
integer | Шаблон подписки. |
sale_price |
number | string | Цена продажи, ₽; без неё — цена из шаблона. |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/memberships \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"plan_id":11,"sale_price":3500}'Ответы
201 Подписка продана.
{
"membership": {
"id": 51,
"card_id": 123,
"plan_id": 11,
"name": "Безлимит на месяц",
"status": "active",
"started_at": "2026-10-24T12:00:00+03:00",
"ends_at": "2026-11-23T12:00:00+03:00",
"remaining_days": 30,
"duration_days": 30,
"sale_price": 3500.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"paused_since": null,
"actions": [
{
"id": 61,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1,
"used_in_window": 1,
"remaining": 0,
"window": "rolling"
}
]
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "membership_issue",
"operation_label": "Продажа подписки",
"mechanic": "membership",
"direction": "neutral",
"amount": 3500.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Продана подписка: Безлимит на месяц",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 Подписки выключены, у клиента уже есть подписка или ошибка в параметрах.
{
"error": "mechanic_disabled",
"message": "Подписки выключены в программе «Кофейня»",
"details": {
"mechanic": "memberships"
}
}{
"error": "operation_rejected",
"message": "У клиента уже есть активная подписка"
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Подписка
GET
/memberships/{id}
Подписка с действиями и остатком лимитов.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Пример запроса
curl https://ankora.pro/api/v2/public/memberships/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Подписка.
{
"membership": {
"id": 51,
"card_id": 123,
"plan_id": 11,
"name": "Безлимит на месяц",
"status": "active",
"started_at": "2026-10-24T12:00:00+03:00",
"ends_at": "2026-11-23T12:00:00+03:00",
"remaining_days": 30,
"duration_days": 30,
"sale_price": 3500.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"paused_since": null,
"actions": [
{
"id": 61,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1,
"used_in_window": 1,
"remaining": 0,
"window": "rolling"
}
]
}
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Использовать действие
POST
/memberships/{id}/actions/{action_id}/use
Отмечает использование действия подписки (например, «Тренировка»). Лимит действия или подписки исчерпан — ошибка limit_reached; force: true отметит сверх лимита (как кнопка «всё равно отметить» у кассира).
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
action_idобяз. |
путь | integer | |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
force |
boolean | |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/memberships/123/actions/61/use \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"location_id":3}'Ответы
200 Действие отмечено.
{
"membership": {
"id": 51,
"card_id": 123,
"plan_id": 11,
"name": "Безлимит на месяц",
"status": "active",
"started_at": "2026-10-24T12:00:00+03:00",
"ends_at": "2026-11-23T12:00:00+03:00",
"remaining_days": 30,
"duration_days": 30,
"sale_price": 3500.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"paused_since": null,
"actions": [
{
"id": 61,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1,
"used_in_window": 1,
"remaining": 0,
"window": "rolling"
}
]
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "membership_use",
"operation_label": "Использование подписки",
"mechanic": "membership",
"direction": "debit",
"amount": 1.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Тренировка",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 Лимит исчерпан или подписка не действует.
{
"error": "limit_reached",
"message": "Лимит исчерпан"
}{
"error": "operation_rejected",
"message": "Подписка на паузе"
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Продлить подписку
POST
/memberships/{id}/extend
Продлевает подписку на срок шаблона. price — цена продления; по умолчанию — из шаблона.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
price |
number | string | Цена продления, ₽; без неё — из шаблона. |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/memberships/123/extend \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"price":3000}'Ответы
200 Продлена.
{
"membership": {
"id": 51,
"card_id": 123,
"plan_id": 11,
"name": "Безлимит на месяц",
"status": "active",
"started_at": "2026-10-24T12:00:00+03:00",
"ends_at": "2026-12-23T12:00:00+03:00",
"remaining_days": 60,
"duration_days": 30,
"sale_price": 3500.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"paused_since": null,
"actions": [
{
"id": 61,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1,
"used_in_window": 1,
"remaining": 0,
"window": "rolling"
}
]
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "membership_extend",
"operation_label": "Продление подписки",
"mechanic": "membership",
"direction": "neutral",
"amount": 3000.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Продлена подписка: Безлимит на месяц",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Поставить на паузу
POST
/memberships/{id}/pause
Пауза останавливает срок подписки; после возобновления дни паузы добавляются к сроку.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
reason |
string |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/memberships/123/pause \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"reason":"Болеет"}'Ответы
200 На паузе.
{
"membership": {
"id": 51,
"card_id": 123,
"plan_id": 11,
"name": "Безлимит на месяц",
"status": "paused",
"started_at": "2026-10-24T12:00:00+03:00",
"ends_at": "2026-11-23T12:00:00+03:00",
"remaining_days": 30,
"duration_days": 30,
"sale_price": 3500.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"paused_since": "2026-10-24T12:00:00+03:00",
"actions": [
{
"id": 61,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1,
"used_in_window": 1,
"remaining": 0,
"window": "rolling"
}
]
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
]
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Снять с паузы
POST
/memberships/{id}/resume
Возобновляет подписку после паузы.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/memberships/123/resume \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)"Ответы
200 Возобновлена.
{
"membership": {
"id": 51,
"card_id": 123,
"plan_id": 11,
"name": "Безлимит на месяц",
"status": "active",
"started_at": "2026-10-24T12:00:00+03:00",
"ends_at": "2026-11-23T12:00:00+03:00",
"remaining_days": 30,
"duration_days": 30,
"sale_price": 3500.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"paused_since": null,
"actions": [
{
"id": 61,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1,
"used_in_window": 1,
"remaining": 0,
"window": "rolling"
}
]
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
]
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Отменить подписку
POST
/memberships/{id}/cancel
Отменяет подписку, при необходимости — с возвратом денег (refund_amount; деньги возвращаете вы). Нужно право ключа «Возвраты и отмены».
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
refund_amount |
number | string | Сколько денег вернули клиенту, ₽ — для учёта. |
reason |
string | |
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/memberships/123/cancel \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"refund_amount":1000,"reason":"Переезд"}'Ответы
200 Отменена.
{
"membership": {
"id": 51,
"card_id": 123,
"plan_id": 11,
"name": "Безлимит на месяц",
"status": "cancelled",
"started_at": "2026-10-24T12:00:00+03:00",
"ends_at": "2026-11-23T12:00:00+03:00",
"remaining_days": 30,
"duration_days": 30,
"sale_price": 3500.0,
"overall_limit_count": null,
"overall_limit_period_days": null,
"paused_since": null,
"actions": [
{
"id": 61,
"label": "Тренировка",
"limit_count": 1,
"limit_period_days": 1,
"used_in_window": 1,
"remaining": 0,
"window": "rolling"
}
]
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "membership_cancel_refund",
"operation_label": "Возврат за подписку",
"mechanic": "membership",
"direction": "debit",
"amount": 1000.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Отмена подписки: Безлимит на месяц",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}403 Операция выключена в правах ключа, или подписка бизнеса истекла.
Нет права ключа
{
"error": "permission_denied",
"message": "Операция выключена в правах ключа: включите «Начисление вручную, установка и корректировка балансов, сумма покупок» в кабинете → Интеграции → «API и Zapier»",
"details": {
"permission": "balance_management"
}
}Подписка истекла
{
"error": "subscription_required",
"message": "Подписка бизнеса истекла — операция интеграции пропущена",
"details": {
"reason": "subscription_expired"
}
}Ещё: 400, 401, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Статус гостя
Визиты, по которым растёт статус гостя.
Засчитать визит
POST
/cards/{id}/guest_visits
Засчитывает визит для статуса гостя. Не больше одного визита в день — повтор вернёт limit_reached. Дошёл до нового статуса — клиенту уходит поздравление.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
location_id |
integer | Точка продажи — операция попадёт в аналитику по точкам. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/cards/123/guest_visits \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"location_id":3}'Ответы
201 Визит засчитан.
{
"guest_visit": {
"id": 81,
"card_id": 123,
"source": "manual",
"visited_at": "2026-10-24T12:00:00+03:00",
"reversed_at": null
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "guest_visit_record",
"operation_label": "Засчитан визит гостя",
"mechanic": "guest_visit",
"direction": "credit",
"amount": 1.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Засчитан визит",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}422 Визит уже засчитан сегодня или статус гостя выключен.
{
"error": "limit_reached",
"message": "Гость уже отмечен сегодня"
}{
"error": "mechanic_disabled",
"message": "Статус гостя выключен в программе «Кофейня»",
"details": {
"mechanic": "guest_status"
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Отменить визит
POST
/guest_visits/{id}/reverse
Отменяет ошибочно засчитанный визит.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
reason |
string |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/guest_visits/123/reverse \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"reason":"Отметили по ошибке"}'Ответы
200 Визит отменён.
{
"guest_visit": {
"id": 81,
"card_id": 123,
"source": "manual",
"visited_at": "2026-10-24T12:00:00+03:00",
"reversed_at": "2026-10-24T12:05:00+03:00"
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"tier": {
"name": "Серебро",
"spend_base": 12500.0,
"cashback_percent": 5.0,
"points_percent": null,
"discount_percent": null
},
"guest_status": null,
"nearest_expiry": {
"date": "2026-11-30T23:59:59+03:00",
"cashback": 40.0,
"points": 0.0,
"stamps": 0
},
"visit_passes": [
],
"membership": null,
"wallet": {
"state": "installed",
"apple_wallet": true,
"google_wallet": false,
"telegram": false,
"web_push": false,
"installed_at": "2026-03-02T10:16:00+03:00",
"uninstalled_at": null
},
"referred_by_card_id": null,
"welcome_bonus_due_at": null
},
"transactions": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "guest_visit_reverse",
"operation_label": "Отменён визит гостя",
"mechanic": "guest_visit",
"direction": "debit",
"amount": 1.0,
"balance_before": null,
"balance_after": null,
"purchase_amount": null,
"description": "Визит отменён",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": null,
"expires_at": null,
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Операции
История всех движений по картам.
История карты
GET
/cards/{id}/transactions
Операции по одной карте страницами по возрастанию id. Фильтры — как у GET /transactions.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
limit |
строка запроса | integer | Сколько записей на странице, от 1 до 100. |
after_id |
строка запроса | integer | Вернуть записи с id больше этого — значение next_after_id из предыдущей страницы. |
operation |
строка запроса | string | Тип операции; несколько — через запятую. |
location_id |
строка запроса | integer | |
created_since |
строка запроса | string | |
created_until |
строка запроса | string |
Пример запроса
curl https://ankora.pro/api/v2/public/cards/123/transactions \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Страница операций карты.
{
"data": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_earn",
"operation_label": "Начисление кэшбека (за покупку)",
"mechanic": "cashback",
"direction": "credit",
"amount": 75.0,
"balance_before": 0.0,
"balance_after": 75.0,
"purchase_amount": 1500.0,
"description": "Кэшбэк 5% с покупки",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": 9000,
"expires_at": "2026-11-30T23:59:59+03:00",
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
],
"has_more": false,
"next_after_id": 9001
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
История операций
GET
/transactions
Все движения по картам бизнеса страницами по возрастанию id: покупки, начисления, списания, сгорания, корректировки, абонементы, подписки, визиты.
Для регулярного забора новых операций храните последний полученный id и передавайте его в after_id.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
limit |
строка запроса | integer | Сколько записей на странице, от 1 до 100. |
after_id |
строка запроса | integer | Вернуть записи с id больше этого — значение next_after_id из предыдущей страницы. |
since_id |
строка запроса | integer | Старое имя after_id, работает так же. |
card_id |
строка запроса | integer | |
customer_id |
строка запроса | integer | Операции по всем картам клиента. |
program_id |
строка запроса | integer | |
location_id |
строка запроса | integer | Операции в точке продажи. |
operation |
строка запроса | string | Тип операции; несколько — через запятую, например cashback_earn,cashback_spend. |
created_since |
строка запроса | string | Не раньше этого момента. Дата 2026-10-01 или время ISO 8601. |
created_until |
строка запроса | string | Раньше этого момента. Дата 2026-10-01 или время ISO 8601. |
Пример запроса
curl https://ankora.pro/api/v2/public/transactions \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Страница операций.
{
"data": [
{
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_earn",
"operation_label": "Начисление кэшбека (за покупку)",
"mechanic": "cashback",
"direction": "credit",
"amount": 75.0,
"balance_before": 0.0,
"balance_after": 75.0,
"purchase_amount": 1500.0,
"description": "Кэшбэк 5% с покупки",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": 9000,
"expires_at": "2026-11-30T23:59:59+03:00",
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
}
],
"has_more": false,
"next_after_id": 9001
}Ещё: 401, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Вебхуки
Подписки на события — Анкора сама отправит их на ваш адрес.
Подписки на вебхуки
GET
/webhooks
Подписки этого ключа — и созданные в кабинете, и через API. Секрет подписи в списке не показывается.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
limit |
строка запроса | integer | Сколько записей на странице, от 1 до 100. |
after_id |
строка запроса | integer | Вернуть записи с id больше этого — значение next_after_id из предыдущей страницы. |
Пример запроса
curl https://ankora.pro/api/v2/public/webhooks \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Страница подписок.
{
"data": [
{
"id": 5,
"url": "https://example.ru/ankora-webhook",
"events": [
"transaction.created",
"card.created"
],
"description": "CRM",
"active": true,
"consecutive_failures": 0,
"disabled_at": null,
"last_success_at": "2026-10-24T12:30:01+03:00",
"last_failure_at": null,
"created_at": "2026-10-20T10:00:00+03:00"
}
],
"has_more": false,
"next_after_id": 5
}Ещё: 401, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Подписаться на события
POST
/webhooks
Создаёт подписку: на url будут приходить выбранные события (формат — в разделе «События вебхуков»). Секрет подписи приходит только в этом ответе — сохраните его; в кабинете он тоже виден.
Адрес — только https и только публичный: внутренние адреса, localhost и логин с паролем в ссылке не принимаются. До 10 подписок на ключ.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
urlобяз. |
string | |
eventsобяз. |
array of WebhookEventType | string | События — массив или строка через запятую. |
description |
string |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/webhooks \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.ru/ankora-webhook","events":["transaction.created","card.created"],"description":"CRM"}'Ответы
201 Подписка создана.
{
"webhook": {
"id": 5,
"url": "https://example.ru/ankora-webhook",
"events": [
"transaction.created",
"card.created"
],
"description": "CRM",
"active": true,
"consecutive_failures": 0,
"disabled_at": null,
"last_success_at": "2026-10-24T12:30:01+03:00",
"last_failure_at": null,
"created_at": "2026-10-20T10:00:00+03:00",
"secret": "whsec_3fk9X2mQ7pL0vT8sN4bR1cY6wZ5aE2dH9jK7uI0oP3q"
}
}422 Адрес не подходит, событий нет или подписок уже 10.
{
"error": "operation_rejected",
"message": "Адрес ведёт во внутреннюю сеть — нужен публичный адрес"
}{
"error": "parameter_missing",
"message": "Не передан параметр url",
"details": {
"param": "url"
}
}Ещё: 400, 401, 403, 404, 409, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Подписка и журнал доставок
GET
/webhooks/{id}
Подписка и последние 20 доставок — с кодом ответа вашего адреса и ошибкой, если была. Журнал хранится 14 дней.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Пример запроса
curl https://ankora.pro/api/v2/public/webhooks/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ"Ответы
200 Подписка.
{
"webhook": {
"id": 5,
"url": "https://example.ru/ankora-webhook",
"events": [
"transaction.created",
"card.created"
],
"description": "CRM",
"active": true,
"consecutive_failures": 0,
"disabled_at": null,
"last_success_at": "2026-10-24T12:30:01+03:00",
"last_failure_at": null,
"created_at": "2026-10-20T10:00:00+03:00"
},
"deliveries": [
{
"id": 901,
"event_id": "evt_6f1c2a9e-5b7d-4e8a-9c41-0d2b6f7e8a10",
"event_type": "transaction.created",
"status": "succeeded",
"attempts": 1,
"last_response_status": 200,
"last_error": null,
"next_attempt_at": null,
"delivered_at": "2026-10-24T12:30:01+03:00",
"created_at": "2026-10-24T12:30:00+03:00"
}
]
}Ещё: 401, 404, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Отписаться
DELETE
/webhooks/{id}
Удаляет подписку и её журнал. Доставки, которые ждали повтора, не уйдут.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Пример запроса
curl -X DELETE https://ankora.pro/api/v2/public/webhooks/123 \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)"Ответы
200 Удалена.
{
"deleted": true,
"id": 5
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
Отправить тестовое событие
POST
/webhooks/{id}/test
Отправляет событие webhook.test сразу, одной попыткой, и возвращает результат — удобно проверить адрес и проверку подписи.
Параметры
| Имя | Где | Тип | Описание |
|---|---|---|---|
idобяз. |
путь | integer | Id из адреса метода — карты, клиента, абонемента, подписки и т.д. |
Idempotency-Key |
заголовок | string | Защита от повтора: уникальная строка на операцию (например, UUID или номер документа), до 255 символов. Повтор успешного запроса с тем же ключом в течение суток вернёт сохранённый ответ с заголовком Idempotent-Replayed: true, а операция не выполнится второй раз. |
Пример запроса
curl -X POST https://ankora.pro/api/v2/public/webhooks/123/test \
-H "Authorization: Bearer ak_ВАШ_КЛЮЧ" \
-H "Idempotency-Key: $(uuidgen)"Ответы
200
Результат доставки — смотрите status и last_response_status.
{
"delivery": {
"id": 901,
"event_id": "evt_6f1c2a9e-5b7d-4e8a-9c41-0d2b6f7e8a10",
"event_type": "webhook.test",
"status": "succeeded",
"attempts": 1,
"last_response_status": 200,
"last_error": null,
"next_attempt_at": null,
"delivered_at": "2026-10-24T12:30:01+03:00",
"created_at": "2026-10-24T12:30:00+03:00"
}
}Адрес ответил ошибкой
{
"delivery": {
"id": 901,
"event_id": "evt_6f1c2a9e-5b7d-4e8a-9c41-0d2b6f7e8a10",
"event_type": "webhook.test",
"status": "failed",
"attempts": 1,
"last_response_status": 500,
"last_error": "Адрес ответил 500",
"next_attempt_at": null,
"delivered_at": null,
"created_at": "2026-10-24T12:30:00+03:00"
}
}Ещё: 400, 401, 403, 404, 409, 422, 429, 500 — общие ошибки, формат и коды — в разделе «Ответы и ошибки».
События вебхуков
Что Анкора присылает на адрес подписки. Как подписаться и проверить подпись — в разделе «Вебхуки».
Новая операция по карте
transaction.created
Любое движение по карте: покупка, начисление, списание, сгорание, корректировка, абонемент, подписка, визит. Что именно — в data.transaction.operation; карта — в состоянии сразу после операции.
Поля data
| Поле | Тип | Описание |
|---|---|---|
data.transaction |
Transaction | Одно движение по карте. |
data.card |
Card |
Карта клиента в одной программе лояльности. В списках — краткая, в остальных ответах — полная (CardFull).
|
Пример тела запроса
{
"id": "evt_6f1c2a9e-5b7d-4e8a-9c41-0d2b6f7e8a10",
"type": "transaction.created",
"created_at": "2026-10-24T12:30:00+03:00",
"business_id": 42,
"data": {
"transaction": {
"id": 9001,
"card_id": 123,
"customer_id": 456,
"program_id": 7,
"operation": "cashback_earn",
"operation_label": "Начисление кэшбека (за покупку)",
"mechanic": "cashback",
"direction": "credit",
"amount": 75.0,
"balance_before": 0.0,
"balance_after": 75.0,
"purchase_amount": 1500.0,
"description": "Кэшбэк 5% с покупки",
"location_id": 3,
"staff_member_id": null,
"source_transaction_id": 9000,
"expires_at": "2026-11-30T23:59:59+03:00",
"expired": false,
"customer_visible": true,
"created_at": "2026-10-24T12:30:00+03:00"
},
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00"
}
}
}Новый клиент программы
card.created
Клиенту выпущена карта в программе — при регистрации, кассиром, из кабинета, интеграцией или через API.
Поля data
| Поле | Тип | Описание |
|---|---|---|
data.card |
Card |
Карта клиента в одной программе лояльности. В списках — краткая, в остальных ответах — полная (CardFull).
|
data.customer |
Customer | Клиент бизнеса со всеми картами. |
Пример тела запроса
{
"id": "evt_0b8e4d2c-1f3a-4c5b-8d9e-7a6b5c4d3e2f",
"type": "card.created",
"created_at": "2026-10-24T12:00:00+03:00",
"business_id": 42,
"data": {
"card": {
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00"
},
"customer": {
"id": 456,
"name": "Анна",
"phone": "+79991234567",
"email": "anna@example.ru",
"birthday": "1990-05-17",
"gender": null,
"custom_fields": {
},
"consent_accepted_at": "2026-03-02T10:15:00+03:00",
"marketing_consent": true,
"marketing_consent_at": "2026-03-02T10:15:00+03:00",
"marketing_unsubscribed_at": null,
"telegram_linked": false,
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"cards": [
{
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00"
}
]
}
}
}Изменился профиль клиента
customer.updated
Изменились контакты, день рождения, пол, поля анкеты, согласия или привязка Telegram. Какие поля — в data.changed_fields.
Поля data
| Поле | Тип | Описание |
|---|---|---|
data.customer |
Customer | Клиент бизнеса со всеми картами. |
data.changed_fields |
array of string |
Пример тела запроса
{
"id": "evt_3c2b1a09-8f7e-4d6c-9b5a-4f3e2d1c0b9a",
"type": "customer.updated",
"created_at": "2026-10-24T12:10:00+03:00",
"business_id": 42,
"data": {
"customer": {
"id": 456,
"name": "Анна",
"phone": "+79991234567",
"email": "anna@example.ru",
"birthday": "1990-05-17",
"gender": null,
"custom_fields": {
},
"consent_accepted_at": "2026-03-02T10:15:00+03:00",
"marketing_consent": true,
"marketing_consent_at": "2026-03-02T10:15:00+03:00",
"marketing_unsubscribed_at": null,
"telegram_linked": false,
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00",
"cards": [
{
"id": 123,
"card_number": "AABBCCDD00000001",
"status": "active",
"customer_id": 456,
"program_id": 7,
"location_id": null,
"cashback_balance": 75.0,
"points_balance": 0.0,
"stamps_count": 3,
"rewards_available": 0,
"total_spent": 12500.0,
"total_visits": 14,
"last_visit_at": "2026-10-24T12:30:00+03:00",
"rfm_segment": "loyal",
"created_at": "2026-03-02T10:15:00+03:00",
"updated_at": "2026-10-24T12:30:00+03:00"
}
]
},
"changed_fields": [
"birthday"
]
}
}Тестовое событие
webhook.test
Приходит по кнопке «Отправить тестовое событие» в кабинете и по POST /webhooks/{id}/test. Подписываться на него не нужно.
Поля data
| Поле | Тип | Описание |
|---|---|---|
data.message |
string | |
data.webhook_id |
integer |
Пример тела запроса
{
"id": "evt_9a8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
"type": "webhook.test",
"created_at": "2026-10-24T12:00:00+03:00",
"business_id": 42,
"data": {
"message": "Тестовое событие Анкоры: подписка https://example.ru/ankora-webhook работает",
"webhook_id": 5
}
}Объекты
Поля объектов в ответах. Поле всегда присутствует; если значения нет — null.
Account
| Поле | Тип | Описание |
|---|---|---|
business |
object | |
business.id |
integer | |
business.name |
string | |
business.slug |
string | Адрес бизнеса в ссылках карт — ankora.pro/<slug>. |
business.timezone |
string | Часовой пояс — в нём считаются даты без смещения. |
subscription |
object | |
subscription.status |
string |
grace — оплаченный период кончился, ждём продления; операции пока работают.
Значения: trial, active, grace, expired
|
subscription.plan |
string | null | Название тарифа. |
subscription.active_until |
string | null | |
subscription.trial_ends_at |
string | null | |
api |
object | |
api.permissions |
object | Права ключа. Включаются в кабинете на странице «API и Zapier». |
api.permissions.balance_management |
boolean | Начисление вручную, установка и корректировка балансов, сумма покупок. |
api.permissions.refunds |
boolean | Возврат покупки и абонемента, отмена подписки. |
api.operations_allowed |
boolean | Можно ли сейчас начислять |
api.blocked_reason |
string | null |
Почему операции закрыты: subscription_expired — подписка истекла, plan_gate — API недоступен на тарифе, billing_gate — интеграция не оплачена.
Значения: subscription_expired, plan_gate, billing_gate
|
api.rate_limit_per_minute |
integer |
Location
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
name |
string | |
address |
string | null | |
latitude |
number | null | |
longitude |
number | null | |
radius_meters |
integer | null | Радиус гео-уведомления. |
nearby_message |
string | null | Текст гео-уведомления на экране блокировки. |
active |
boolean | |
geo_program_ids |
array of integer | Программы, картам которых точка шлёт гео-уведомления; пусто — всем. |
created_at |
string | |
updated_at |
string |
Program
Программа лояльности со всеми настройками механик.
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
name |
string | |
active |
boolean | |
cashback |
object | |
cashback.enabled |
boolean | |
cashback.percent |
number | Базовый процент кэшбэка от покупки. |
cashback.tiers |
array of PercentTier | |
cashback.auto_award |
boolean | Начислять автоматически с каждой покупки. |
cashback.max_balance |
number | null | Потолок накопления |
cashback.max_redemption_percent |
number | Сколько процентов чека можно оплатить кэшбэком. |
cashback.expiry |
BalanceExpiry | Сгорание баланса. |
cashback.description |
string | null | |
points |
object | |
points.enabled |
boolean | |
points.percent |
number | Базовый процент: сколько баллов начисляется со 100 ₽ покупки. |
points.tiers |
array of PercentTier | |
points.auto_award |
boolean | |
points.currency_name |
string | Как называются баллы у бизнеса. |
points.redemption_rate |
number | Сколько рублей скидки даёт один балл. |
points.max_balance |
number | null | |
points.max_redemption_percent |
number | |
points.expiry |
BalanceExpiry | Сгорание баланса. |
points.description |
string | null | |
stamps |
object | |
stamps.enabled |
boolean | |
stamps.target |
integer | null | Сколько штампов до награды. |
stamps.reward_description |
string | null | |
stamps.auto_reset |
boolean | null | Начинать новый круг штампов после награды. |
stamps.expiry |
object | |
stamps.expiry.enabled |
boolean | |
stamps.expiry.days |
integer | null | |
stamps.expiry.mode |
string |
per_stamp — каждый штамп сгорает сам; cycle — весь круг сгорает, если не собран за срок.
Значения: per_stamp, cycle
|
stamps.description |
string | null | |
discount |
object | |
discount.enabled |
boolean | |
discount.percent |
number | |
discount.tiers |
array of PercentTier | |
discount.description |
string | null | |
tier_windows |
object |
За какой период считается сумма покупок для ступени и визиты для статуса гостя; null — за всё время.
|
tier_windows.spend_months |
integer | null | |
tier_windows.visits_months |
integer | null | |
tier_windows.drop_reminder |
object | |
tier_windows.drop_reminder.enabled |
boolean | |
tier_windows.drop_reminder.days |
integer | За сколько дней предупредить клиента |
guest_status |
object | |
guest_status.enabled |
boolean | |
guest_status.counting_mode |
string |
manual — визит засчитывает кассир; purchase — каждая покупка.
Значения: manual, purchase
|
guest_status.tiers |
array of object | |
guest_status.tiers[].threshold |
integer | С какого числа визитов. |
guest_status.tiers[].name |
string | null | |
guest_status.tiers[].perk |
string | null | |
guest_status.tiers[].color |
string | null | |
guest_status.description |
string | null | |
welcome_bonus |
object | |
welcome_bonus.enabled |
boolean | |
welcome_bonus.type |
string |
Значения: points, cashback
|
welcome_bonus.amount |
number | |
welcome_bonus.expiry_days |
integer | null | |
welcome_bonus.delay_hours |
integer | Через сколько часов после регистрации придёт бонус. |
welcome_bonus.after_first_purchase |
boolean | Начислять после первой покупки |
welcome_bonus.message |
string | null | |
birthday_bonus |
object | |
birthday_bonus.enabled |
boolean | |
birthday_bonus.gift |
boolean |
false — только поздравление, без бонуса.
|
birthday_bonus.type |
string |
Значения: points, cashback
|
birthday_bonus.amount |
number | |
birthday_bonus.days_before |
integer | null | |
birthday_bonus.expiry_days |
integer | null | |
birthday_bonus.message |
string | null | |
birthday_bonus.greeting_message |
string | null | |
referral |
object | |
referral.enabled |
boolean | |
referral.type |
string |
Значения: points, cashback
|
referral.recipients |
string |
Кому начисляется бонус: обоим, только приглашённому или только пригласившему.
Значения: both, referee, referrer
|
referral.referee_amount |
number | |
referral.referrer_amount |
number | |
referral.message |
string | null | |
expiry_reminders |
object | |
expiry_reminders.enabled |
boolean | |
expiry_reminders.days |
array of integer | За сколько дней до сгорания напомнить. |
expiry_reminders.message |
string | null | |
visit_passes |
object | |
visit_passes.enabled |
boolean | |
visit_passes.default_expiry_days |
integer | null | |
visit_passes.grant_cashback |
boolean | Начислять кэшбэк за покупку абонемента. |
visit_passes.notify_exhausted |
boolean | |
memberships |
object | |
memberships.enabled |
boolean | |
memberships.expiry_reminder_days |
integer | |
memberships.plans |
array of MembershipPlan | |
registration_fields |
array of object |
Поля анкеты регистрации. Стандартные ключи — phone, name, email, birthday, gender; остальные попадают в custom_fields клиента.
|
registration_fields[].key |
string | |
registration_fields[].label |
string | |
registration_fields[].type |
string | |
registration_fields[].required |
boolean | |
created_at |
string | |
updated_at |
string |
PercentTier
Ступень по сумме покупок.
| Поле | Тип | Описание |
|---|---|---|
threshold |
number | С какой суммы покупок действует ступень |
percent |
number | |
name |
string | null | |
color |
string | null | Цвет карты на этой ступени. |
BalanceExpiry
Сгорание баланса.
| Поле | Тип | Описание |
|---|---|---|
enabled |
boolean | |
days |
integer | null | |
policy |
string |
from_earn — через days дней после начисления; from_last_activity — через days дней без покупок; fixed_date — в дату fixed_date.
Значения: from_earn, from_last_activity, fixed_date
|
fixed_date |
string | null |
MembershipPlan
Шаблон подписки — его продают клиенту.
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
name |
string | |
description |
string | null | |
duration_days |
integer | |
suggested_sale_price |
number | |
suggested_renewal_price |
number | |
overall_limit_count |
integer | null | |
overall_limit_period_days |
integer | null | |
actions |
array of object | |
actions[].id |
integer | |
actions[].label |
string | |
actions[].limit_count |
integer | null | |
actions[].limit_period_days |
integer | null |
Promotion
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
program_id |
integer | |
name |
string | |
kind |
string |
Значения: bonus, multiplier
|
state |
string |
Значения: draft, scheduled, launching, active, finished, cancelled
|
starts_at |
string | null | |
ends_at |
string | null | |
bonus |
object | null |
Для kind = bonus — подарок каждому в аудитории.
|
multiplier |
object | null |
Для kind = multiplier — во сколько раз растёт начисление.
|
message |
string | null | Текст уведомления клиентам. |
card_text |
string | null | Строка на карте в Wallet на время акции. |
control_group_percent |
integer | Доля аудитории |
cards_count |
integer | |
control_count |
integer | |
launched_at |
string | null | |
finished_at |
string | null | |
cancelled_at |
string | null | |
created_at |
string |
Customer
Клиент бизнеса со всеми картами.
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
name |
string | null | |
phone |
string | null | |
email |
string | null | |
birthday |
string | null | |
gender |
string | null | |
custom_fields |
object | Дополнительные поля анкеты, ключи — из настроек регистрации программы. |
consent_accepted_at |
string | null | Согласие на обработку персональных данных. |
marketing_consent |
boolean | Действующее согласие на рекламные рассылки. |
marketing_consent_at |
string | null | |
marketing_unsubscribed_at |
string | null | |
telegram_linked |
boolean | |
created_at |
string | |
updated_at |
string | |
cards |
array of Card |
CustomerFull
Профиль клиента — как в списке, но карты полные.
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
name |
string | null | |
phone |
string | null | |
email |
string | null | |
birthday |
string | null | |
gender |
string | null | |
custom_fields |
object | Дополнительные поля анкеты, ключи — из настроек регистрации программы. |
consent_accepted_at |
string | null | Согласие на обработку персональных данных. |
marketing_consent |
boolean | Действующее согласие на рекламные рассылки. |
marketing_consent_at |
string | null | |
marketing_unsubscribed_at |
string | null | |
telegram_linked |
boolean | |
created_at |
string | |
updated_at |
string | |
cards |
array of CardFull |
Card
Карта клиента в одной программе лояльности. В списках — краткая, в остальных ответах — полная (CardFull).
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
card_number |
string | |
status |
string |
Значения: active, suspended, expired
|
customer_id |
integer | |
program_id |
integer | |
location_id |
integer | null | Точка |
cashback_balance |
number | Кэшбэк |
points_balance |
number | Баллы. |
stamps_count |
integer | Штампы в текущем круге. |
rewards_available |
integer | Награды за штампы |
total_spent |
number | Сумма покупок за всё время |
total_visits |
integer | Число покупок. |
last_visit_at |
string | null | |
rfm_segment |
RfmSegment | null | |
created_at |
string | |
updated_at |
string | Меняется при любой операции по карте. |
CardFull
Полная карта — с текущей ступенью, статусом гостя, ближайшим сгоранием, абонементами, подпиской и тем, где карта у клиента.
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
card_number |
string | |
status |
string |
Значения: active, suspended, expired
|
customer_id |
integer | |
program_id |
integer | |
location_id |
integer | null | Точка |
cashback_balance |
number | Кэшбэк |
points_balance |
number | Баллы. |
stamps_count |
integer | Штампы в текущем круге. |
rewards_available |
integer | Награды за штампы |
total_spent |
number | Сумма покупок за всё время |
total_visits |
integer | Число покупок. |
last_visit_at |
string | null | |
rfm_segment |
RfmSegment | null | |
created_at |
string | |
updated_at |
string | Меняется при любой операции по карте. |
tier |
CardTier |
Текущая ступень и действующие проценты. null у процента — механика выключена.
|
guest_status |
GuestStatus | null | Статус гостя по числу визитов. |
nearest_expiry |
NearestExpiry | null | Что сгорит в ближайшую дату. |
visit_passes |
array of VisitPass | Действующие абонементы. |
membership |
Membership | null | Действующая подписка. |
wallet |
Wallet | Где карта у клиента и куда доходят уведомления. |
referred_by_card_id |
integer | null | Карта пригласившего по реферальной программе. |
welcome_bonus_due_at |
string | null | Когда придёт отложенный приветственный бонус. |
CardTier
Текущая ступень и действующие проценты. null у процента — механика выключена.
| Поле | Тип | Описание |
|---|---|---|
name |
string | null | Название ступени |
spend_base |
number | Сумма покупок |
cashback_percent |
number | null | |
points_percent |
number | null | |
discount_percent |
number | null |
GuestStatus
Статус гостя по числу визитов.
| Поле | Тип | Описание |
|---|---|---|
name |
string | null | |
visits |
integer | |
perk |
string | null | Что даёт статус. |
next_name |
string | null | |
visits_left |
integer | null | Визитов до следующего статуса. |
visited_today |
boolean |
NearestExpiry
Что сгорит в ближайшую дату.
| Поле | Тип | Описание |
|---|---|---|
date |
string | |
cashback |
number | |
points |
number | |
stamps |
integer |
Wallet
Где карта у клиента и куда доходят уведомления.
| Поле | Тип | Описание |
|---|---|---|
state |
string |
installed — карта в Apple Wallet или Google Wallet; removed — была и удалена.
Значения: not_installed, installed, removed
|
apple_wallet |
boolean | |
google_wallet |
boolean | |
telegram |
boolean | Клиент подключил Telegram-бота карты. |
web_push |
boolean | Включены уведомления в браузере. |
installed_at |
string | null | |
uninstalled_at |
string | null |
VisitPass
Абонемент — пакет визитов.
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
card_id |
integer | |
title |
string | |
state |
string |
Значения: active, frozen, exhausted, expired, refunded
|
total_visits |
integer | |
used_visits |
integer | |
remaining_visits |
integer | |
price |
number | |
expires_at |
string | null | |
frozen_since |
string | null | |
last_usage_id |
integer | null | Последний засчитанный визит — его можно отменить. |
created_at |
string |
Membership
Подписка клиента с лимитами действий.
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
card_id |
integer | |
plan_id |
integer | |
name |
string | |
status |
string |
Значения: active, paused, expired, cancelled
|
started_at |
string | |
ends_at |
string | |
remaining_days |
integer | |
duration_days |
integer | |
sale_price |
number | |
overall_limit_count |
integer | null | |
overall_limit_period_days |
integer | null | |
paused_since |
string | null | |
actions |
array of MembershipAction |
MembershipAction
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
label |
string | |
limit_count |
integer | null | |
limit_period_days |
integer | null | |
used_in_window |
integer | |
remaining |
integer | null |
null — без лимита.
|
window |
string |
Значения: unlimited, lifetime, rolling
|
Transaction
Одно движение по карте.
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
card_id |
integer | |
customer_id |
integer | |
program_id |
integer | |
operation |
TransactionOperation | Тип операции. |
operation_label |
string | Название операции по-русски. |
mechanic |
string | null |
Значения: points, cashback, stamps, purchase, total_spent, visit_pass, membership, guest_visit
|
direction |
string |
credit — начисление, debit — списание, neutral — покупка или оплата подписки.
Значения: credit, debit, neutral
|
amount |
number |
Всегда больше нуля; направление — в direction. Единица — по механике: ₽, баллы, штампы, визиты.
|
balance_before |
number | null | |
balance_after |
number | null | |
purchase_amount |
number | null | Сумма покупки |
description |
string | null | |
location_id |
integer | null | |
staff_member_id |
integer | null | Сотрудник |
source_transaction_id |
integer | null | Операция |
expires_at |
string | null | Когда сгорит начисление. |
expired |
boolean | |
customer_visible |
boolean | Видна ли операция клиенту в истории карты. |
created_at |
string |
CheckoutPreview
| Поле | Тип | Описание |
|---|---|---|
amount |
number | Сумма чека. |
discount_percent |
number | Скидка по ступени клиента. |
discount_amount |
number | |
after_discount |
number | |
cashback |
CheckoutMechanicPreview | |
points |
CheckoutMechanicPreview | |
promotion_multipliers |
object |
Множители идущих акций — уже учтены в earn.
|
promotion_multipliers.cashback |
number | |
promotion_multipliers.points |
number | |
to_pay |
number | Сколько клиент платит деньгами. |
CheckoutMechanicPreview
| Поле | Тип | Описание |
|---|---|---|
enabled |
boolean | |
available |
number | Баланс на карте. |
max_redeemable |
number | Сколько можно списать по этому чеку: не больше баланса и лимита программы. |
redeem |
number | Сколько списывается в этом расчёте. |
earn_percent |
number | Процент начисления по ступени клиента. |
earn |
number | Сколько начислится с оплаченной суммы |
auto_award |
boolean |
false — программа в ручном режиме: начисляет кассир, передайте cashback_to_add или points_to_add.
|
max_manual_award |
number | null | Сколько можно начислить вручную в ручном режиме. |
Webhook
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
url |
string | |
events |
array of WebhookEventType | |
description |
string | null | |
active |
boolean |
false — выключена: вами или после трёх суток отказов адреса.
|
consecutive_failures |
integer | Отказов подряд. |
disabled_at |
string | null | |
last_success_at |
string | null | |
last_failure_at |
string | null | |
created_at |
string |
WebhookDelivery
| Поле | Тип | Описание |
|---|---|---|
id |
integer | |
event_id |
string |
Совпадает с id события и заголовком Ankora-Event-Id — по нему отсекайте дубли.
|
event_type |
string | |
status |
string |
pending — ждёт повтора.
Значения: pending, succeeded, failed
|
attempts |
integer | |
last_response_status |
integer | null | Код ответа вашего адреса. |
last_error |
string | null | |
next_attempt_at |
string | null | |
delivered_at |
string | null | |
created_at |
string |
Error
Ошибка. Код в error стабилен — по нему ветвится ваш код; message — текст для человека.
| Поле | Тип | Описание |
|---|---|---|
error |
string |
Значения: unauthorized, permission_denied, subscription_required, invalid_json, parameter_missing, parameter_invalid, not_found, program_required, mechanic_disabled, insufficient_balance, redemption_limit_exceeded, limit_reached, operation_rejected, idempotency_key_reused, idempotency_key_in_progress, rate_limited, internal_error
|
message |
string | |
details |
object | Подробности, свои у каждого кода — см. раздел «Ошибки». |
TransactionOperation
Тип операции в истории — поле operation. Направление движения — в direction, название для человека — в operation_label.
| Значение | Что это |
|---|---|
points_earn | Начисление баллов (за покупку) |
points_spend | Списание баллов |
points_expire | Сгорание баллов |
points_adjust | Корректировка баллов |
points_set | Установка баланса баллов |
points_add | Начисление баллов |
cashback_earn | Начисление кэшбека (за покупку) |
cashback_spend | Списание кэшбека |
cashback_expire | Сгорание кэшбека |
cashback_adjust | Корректировка кэшбека |
cashback_set | Установка баланса кэшбека |
cashback_add | Начисление кэшбека |
stamp_add | Добавление штампа |
stamp_redeem | Награда за штампы |
stamp_adjust | Корректировка штампов |
reward_use | Использование награды |
stamp_expire | Сгорание штампа |
stamp_cycle_expire | Сгорание цикла штампов |
purchase_record | Покупка |
total_spent_increase | Увеличение суммы покупок |
total_spent_decrease | Уменьшение суммы покупок |
visit_pass_issue | Продажа абонемента |
visit_pass_use | Списан визит абонемента |
visit_pass_reverse | Отмена визита абонемента |
visit_pass_refund | Возврат за абонемент |
visit_pass_expire | Истёк срок абонемента |
membership_issue | Продажа подписки |
membership_extend | Продление подписки |
membership_use | Использование подписки |
membership_cancel_refund | Возврат за подписку |
guest_visit_record | Засчитан визит гостя |
guest_visit_reverse | Отменён визит гостя |
guest_visits_reset | Обнуление визитов гостя |
RfmSegment
RFM-сегмент карты — по давности, частоте и сумме покупок. Пересчитывается ночью.
| Значение | Сегмент |
|---|---|
champions | Чемпионы |
loyal | Лояльные |
potential_loyalists | Потенциально лояльные |
new_customers | Новые |
promising | Многообещающие |
need_attention | Требуют внимания |
about_to_sleep | Скоро уснут |
at_risk | Под угрозой ухода |
cant_lose_them | Нельзя потерять |
hibernating | Спящие |
lost | Потерянные |
История изменений
Октябрь 2026 — версия 2.0
- Новые методы: аккаунт, точки, программы со всеми настройками механик, акции, профиль клиента и его правка, карта и её история, продажа с расчётом, возврат покупки, начисление вручную, установка и корректировка балансов, сумма покупок, снятие штампов, абонементы, подписки, визиты статуса гостя, вебхуки.
- Ошибки: поле
error— стабильный код вместо фразы, текст — вmessage, подробности — вdetails.GET /customers/searchбез результата отвечает404 not_foundв том же формате. - Списки
GET /customersиGET /transactions— в виде{ data, has_more, next_after_id }, по возрастанию id, с фильтрами. ЭлементGET /customers— клиент со всеми картами, а не карта.since_idработает какafter_id. - Клиента можно указать номером карты, id карты или клиента и программой — во всех методах, включая методы первой версии.
- Карта в ответах — полная: к полям первой версии добавились ступень, ближайшее сгорание, абонементы, подписка и Wallet.
POST /stampsпри выключенных штампах отвечаетmechanic_disabled.- Защита от повтора
Idempotency-Key, точка продажиlocation_id, права ключа, ответы 429 и 500 — в JSON.
Ключ API — в кабинете Анкоры
7 дней бесплатно. Включите «API и Zapier» в разделе «Интеграции» и сделайте первый запрос за пять минут.
Начать бесплатно