{"openapi":"3.0.3","info":{"title":"Мои Места — Public API","version":"2.1.0","description":"Два независимых API платформы Мои Места в одной спеке:\n\n1. **Registration API** — публичный API самостоятельной регистрации компании.\n   Все эндпоинты тега «Регистрация» и «Аутентификация» открыты (без авторизации).\n\n2. **Company Management API** (/api/v1/*) — REST API управления подарками и акциями\n   для AI-агентов и интеграций. Требует API-ключа компании (Bearer mm_…).\n\nВАЖНО ПРО АДРЕСА: Эта спека опубликована на лендинге по адресу\nhttps://moimesta.ru/api/openapi.yaml, однако сам API живёт на\nhttps://company.moimesta.ru/api. Используйте адрес из поля servers\n(https://company.moimesta.ru/api), а не адрес, по которому получена спека.\nПути в этой спеке указаны относительно servers[0].url — полный адрес\nэндпоинта получается склейкой servers[0].url и пути (например, /v1/me\nдаёт https://company.moimesta.ru/api/v1/me).\n\nКРИТИЧНЫЙ QUIRK ОБРАБОТКИ ОШИБОК: Бизнес-ошибки эндпоинтов\n/auth/singup, /auth/singupGetCode и /auth/checkPhone возвращаются с\nHTTP 200 и полем errorMessage в теле ответа — анализируйте тело, а не\nтолько HTTP-статус. Коды 400 означают только ошибку схемы (валидация JSON),\n429 — превышение rate-limit, 500 — сбой сервера.\nЭндпоинты /auth/restore/* отдают ошибки через HTTP 400 с детализацией\nв поле data.\n"},"servers":[{"url":"https://company.moimesta.ru/api","description":"Продакшн"}],"security":[],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT access-токен, полученный после регистрации или входа.\nТребуется только для защищённых эндпоинтов после регистрации.\nВсе регистрационные шаги выполняются без авторизации.\n"},"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key","description":"API-ключ компании из личного кабинета (ЛКБ) на company.moimesta.ru.\nФормат: mm_ + 32 hex-символа (пример: mm_0123456789abcdef0123456789abcdef).\nПередаётся заголовком: Authorization: Bearer mm_…\nКлюч привязан к конкретной компании; companyId выводится из ключа\nавтоматически — передавать его в теле или URL не нужно.\nКаждый ключ имеет набор scope (gifts:read, gifts:write, promotions:read,\npromotions:write, stats:read). Эндпоинт GET /api/v1/me возвращает\nтекущие scopes без авторизационных данных бизнеса.\n\nУСЛОВИЕ РАБОТЫ КЛЮЧА: API-ключ действует только пока у компании активен\nпробный период ИЛИ оплаченная подписка. Если оба неактивны, любой вызов\n/api/v1/* возвращает HTTP 402 (Payment Required) с телом\n{ error, message, entitlement }. После активации пробного периода или\nоплаты подписки ключ снова начинает работать в течение ~30 секунд —\nотзывать или пересоздавать ключ не нужно.\n"}},"schemas":{"Category":{"type":"object","required":["categoryId","title","iconUrl"],"properties":{"categoryId":{"type":"integer","example":1},"title":{"type":"string","example":"Кафе и рестораны"},"iconUrl":{"type":"string","example":"https://s3.moimesta.ru/moimesta-static/icons/cafe.svg"}}},"CategoryWithSubcategories":{"allOf":[{"$ref":"#/components/schemas/Category"},{"type":"object","properties":{"subcategories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}}}]},"CheckPhoneResponse":{"type":"object","required":["userExist","companyExist"],"properties":{"userExist":{"type":"boolean","example":false},"companyExist":{"type":"boolean","example":false},"errorMessage":{"type":"string","description":"Присутствует при бизнес-ошибке (HTTP 200). Анализируйте тело ответа,\nа не только HTTP-статус.\n"}}},"SendOtpRequest":{"type":"object","required":["phone"],"properties":{"phone":{"type":"number","description":"РФ-номер из 10 цифр без +7","example":9991234567}}},"SendOtpResponse":{"type":"object","required":["oneTimePasswordSent","retryAfter"],"properties":{"oneTimePasswordSent":{"oneOf":[{"type":"string","enum":["sms","call","telegram","max"]},{"type":"boolean","enum":[false]}],"description":"Канал доставки OTP или false при бизнес-ошибке.\n"},"smsCodeNumber":{"type":"integer","description":"Номер SMS-сообщения (не сам код), может отсутствовать","example":42},"retryAfter":{"type":"integer","description":"Секунды до следующей попытки","example":180},"errorMessage":{"type":"string","description":"Присутствует при бизнес-ошибке. Возможные значения:\n\"time limit\" — повтор слишком рано, ждать retryAfter;\n\"company Exist\" — компания уже зарегистрирована на этом номере;\n\"unknown error\" — сбой отправки.\n","example":"time limit"}}},"SignupRequest":{"type":"object","required":["phone","email","confirmCode","companyName","categoryId","password"],"properties":{"phone":{"type":"number","description":"РФ-номер из 10 цифр без +7","example":9991234567},"email":{"type":"string","format":"email","example":"owner@example.ru"},"confirmCode":{"type":"string","pattern":"^\\d{4}$","description":"4-значный OTP-код из шага singupGetCode","example":"4821"},"companyName":{"type":"string","description":"Название компании, не пустое после trim","example":"Кофейня «Утро»"},"categoryId":{"type":"integer","description":"ID категории из GET /categories","example":1},"password":{"type":"string","description":"6–50 символов, обязателен для нового пользователя","example":"MyPass123"},"username":{"type":"string","description":"Имя, 3–30 символов, обязателен для нового пользователя (ветка A)","example":"Иван"},"userSurname":{"type":"string","description":"Фамилия, 3–30 символов, обязателен для нового пользователя (ветка A)","example":"Петров"}}},"SignupUser":{"type":"object","required":["userId","userName","companyId","title","balance","status"],"properties":{"userId":{"type":"integer","example":123456},"userName":{"type":"string","example":"Иван"},"companyId":{"type":"integer","example":78910},"title":{"type":"string","example":"Кофейня «Утро»"},"balance":{"type":"number","example":0},"status":{"type":"object","properties":{"activated":{"type":"boolean","example":true},"isTrialPeriodActive":{"type":"boolean","example":true}}}}},"SignupResponse":{"type":"object","properties":{"accessToken":{"type":"string","description":"JWT access-токен (при успехе)","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"refreshToken":{"type":"string","description":"JWT refresh-токен (при успехе)","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"user":{"$ref":"#/components/schemas/SignupUser"},"errorMessage":{"type":"string","description":"Присутствует при бизнес-ошибке (HTTP 200). Возможные значения:\n\"not match\" — неверный код;\n\"code expired\" — код старше 3 минут, запросить новый;\n\"error\" — нет отправленного кода для номера;\n\"company Exist\" — компания уже есть;\n\"user data required\" — не переданы password/username/userSurname;\n\"invalid company data\" — пустой companyName или несуществующий categoryId.\n"}}},"RestoreOtpRequest":{"type":"object","required":["phone"],"properties":{"phone":{"type":"number","description":"РФ-номер из 10 цифр без +7","example":9991234567}}},"RestoreOtpResponse":{"type":"object","properties":{"oneTimePasswordSent":{"type":"string","enum":["sms","call","telegram"],"example":"sms"},"retryAfter":{"type":"integer","example":180},"smsCodeNumber":{"type":"integer","example":42}}},"RestoreChangePasswordRequest":{"type":"object","required":["phone","oneTimePassword","password","confirmPassword"],"properties":{"phone":{"type":"number","description":"РФ-номер из 10 цифр без +7","example":9991234567},"oneTimePassword":{"type":"string","pattern":"^\\d{4}$","description":"4-значный OTP из шага restore/one-time-password","example":"4821"},"password":{"type":"string","description":"Новый пароль, 6–50 символов","example":"NewPass123"},"confirmPassword":{"type":"string","description":"Должен совпадать с password","example":"NewPass123"}}},"AuthLoginRequest":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string","description":"Телефон в виде строки (10 цифр)","example":"9991234567"},"password":{"type":"string","example":"MyPass123"}}},"AuthTokensResponse":{"type":"object","properties":{"accessToken":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"refreshToken":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"user":{"$ref":"#/components/schemas/SignupUser"}}},"AccessTokenRequest":{"type":"object","required":["accessToken"],"properties":{"accessToken":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}}},"AccessTokenResponse":{"type":"object","properties":{"accessToken":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"user":{"$ref":"#/components/schemas/SignupUser"}}},"RefreshTokenRequest":{"type":"object","required":["refreshToken"],"properties":{"refreshToken":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","example":"error"},"message":{"type":"string"}}},"RateLimitError":{"type":"object","properties":{"message":{"type":"string","example":"Too many OTP requests for this phone"}}},"RestoreError":{"type":"object","properties":{"status":{"type":"string","example":"error"},"message":{"type":"string"},"data":{"type":"object","description":"Содержит ключ с причиной ошибки:\ncannotBeSended — нет компании на номере или слишком частый запрос;\ninvalidOneTimePassword — код не совпал;\ninvalidUser — нет прав или компании;\ninvalidPassword — password не совпадает с confirmPassword.\n"}}},"ApiKeyMeResponse":{"type":"object","required":["companyId","scopes"],"properties":{"companyId":{"type":"integer","description":"ID компании, к которой привязан ключ","example":78910},"companyName":{"type":"string","nullable":true,"description":"Название компании (null если не удалось получить)","example":"Кофейня «Утро»"},"scopes":{"type":"array","items":{"type":"string","enum":["gifts:read","gifts:write","promotions:read","promotions:write","stats:read"]},"description":"Список scope, доступных этому ключу","example":["gifts:read","promotions:read"]}}},"GiftType":{"type":"string","enum":["certificate","discountCoupon","bonusesCoupon","bonusReward"],"description":"Тип подарка. Значения camelCase — snake_case (discount_coupon и т.п.) не\nраспознаётся валидацией и вернёт HTTP 400 validation_error:\n- certificate — Сертификат (valuePrice — номинал в рублях)\n- discountCoupon — Скидка / купон на скидку (discountPercent — процент скидки)\n- bonusesCoupon — Бонусы / бонусный купон (bonusesAmount — кол-во монет, bonusesPercent — процент)\n- bonusReward — Подарочные бонусы / бонусное вознаграждение (bonusesAmount — монеты, rewardTTL — дни жизни монет)\n"},"GiftBase":{"type":"object","required":["giftId","title","type","startedAt","expiredAt"],"properties":{"id":{"type":"integer","description":"Канонический идентификатор для путей GET/обновления /{id} (для подарков совпадает с giftId). Правило: какой `id` пришёл в ответе — такой и подставляйте в путь. Не используйте promotionId.","example":1001},"giftId":{"type":"integer","example":1001},"title":{"type":"string","description":"Название подарка","example":"Скидка 10% на кофе"},"type":{"$ref":"#/components/schemas/GiftType"},"description":{"type":"string","description":"Описание подарка (может содержать HTML из разметки)","example":"Подарите клиенту скидку 10% на любой кофе"},"condition":{"type":"string","description":"Условие получения подарка","example":"При покупке от 500 рублей"},"pictureUrls":{"type":"array","items":{"type":"string","format":"uri"},"description":"Ссылки на изображения подарка"},"startedAt":{"type":"integer","format":"int64","description":"Дата начала действия (unix timestamp, мс)","example":1720000000000},"expiredAt":{"type":"integer","format":"int64","description":"Дата окончания действия (unix timestamp, мс)","example":1730000000000},"valuePrice":{"type":"number","description":"Номинал сертификата в рублях (только для type=certificate)","example":500},"discountPercent":{"type":"number","description":"Процент скидки (только для type=discountCoupon)","example":10},"bonusesAmount":{"type":"integer","description":"Количество монет (только для type=bonusesCoupon и bonusReward)","example":50},"bonusesPercent":{"type":"number","description":"Процент бонусов (только для type=bonusesCoupon)","example":5},"rewardTTL":{"type":"integer","description":"Время жизни монет в днях (только для type=bonusReward)","example":30},"hide":{"type":"boolean","description":"Скрыт ли подарок","example":false},"moderation":{"type":"string","nullable":true,"description":"Статус модерации (pending/approved/rejected/null)","example":"approved"}}},"GiftCreateRequest":{"type":"object","required":["title","type","startedAt","expiredAt"],"properties":{"title":{"type":"string","description":"Название подарка (не пустое)","example":"Скидка 10% на кофе"},"type":{"$ref":"#/components/schemas/GiftType"},"description":{"type":"string","description":"Описание (HTML разрешён)","example":"Подарите клиенту скидку 10% на любой кофе"},"condition":{"type":"string","description":"Условие получения","example":"При покупке от 500 рублей"},"startedAt":{"type":"integer","format":"int64","description":"Начало действия (unix timestamp, мс)","example":1720000000000},"expiredAt":{"type":"integer","format":"int64","description":"Конец действия (unix timestamp, мс)","example":1730000000000},"valuePrice":{"type":"number","description":"Номинал сертификата (обязателен для type=certificate)","example":500},"discountPercent":{"type":"number","description":"Процент скидки (обязателен для type=discountCoupon)","example":10},"bonusesAmount":{"type":"integer","description":"Кол-во монет (обязателен для type=bonusesCoupon, bonusReward)","example":50},"bonusesPercent":{"type":"number","description":"Процент бонусов (для type=bonusesCoupon)","example":5},"rewardTTL":{"type":"integer","description":"Время жизни монет в днях (для type=bonusReward)","example":30},"pictures":{"type":"array","maxItems":3,"description":"Изображения подарка — массив строк, до 3 штук.\nКаждый элемент — либо base64 data-URI (data:image/jpeg;base64,… или\ndata:image/png;base64,…), либо уже существующий URL изображения.\nПервый элемент становится обложкой подарка.\nКартинки передаются инлайном; сервер сохраняет изображение самостоятельно.\nРекомендуемое соотношение сторон: 16:9. Максимальный размер: 2 МБ на фото.\n","items":{"type":"string"},"example":["data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."]}}},"GiftListResponse":{"type":"object","required":["items","rows"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/GiftBase"}},"rows":{"type":"integer","description":"Общее кол-во подарков (для пагинации)","example":42}}},"GiftStatsResponse":{"type":"object","properties":{"gift":{"$ref":"#/components/schemas/GiftBase"},"countCompaniesBuyed":{"type":"integer","description":"Кол-во компаний, купивших подарок","example":5},"countNewClients":{"type":"integer","description":"Кол-во новых клиентов","example":12},"countNotApplied":{"type":"integer","description":"Не применено","example":3},"countApplied":{"type":"integer","description":"Применено","example":20},"countUsed":{"type":"integer","description":"Использовано","example":18},"countDeclined":{"type":"integer","description":"Отклонено","example":2},"turnOver":{"type":"number","description":"Оборот (рублей)","example":9500}}},"ApiV1Error":{"type":"object","required":["error"],"description":"Стандартный формат ошибки для всех эндпоинтов /api/v1.\nТело НИКОГДА не содержит внутренних деталей (имён таблиц, стека, SQL).\nПоле error — стабильный машиночитаемый код; поле message — человекочитаемое описание.\nПри ошибке валидации присутствует массив fields с детализацией по полям.\n","properties":{"error":{"type":"string","description":"Стабильный код ошибки (snake_case). Основные коды:\n- invalid_api_key — ключ не найден или отозван (HTTP 401)\n- insufficient_scope — нет нужного scope (HTTP 403)\n- validation_error — некорректные поля запроса (HTTP 400)\n- gift_after_share_time — срок действия подарка не перекрывает период акции + 3 дня (HTTP 400)\n- not_enough_gift_amount — недостаточно доступных подарков (HTTP 400)\n- invalid_promotion_dates — некорректные даты акции (HTTP 400)\n- promocode_not_verified — акция ещё не прошла модерацию (HTTP 400)\n- card_codes_empty — список кодов карт пуст (HTTP 400)\n- card_codes_limit_exceeded — карт больше 1000 (HTTP 400)\n- card_not_found — карта не найдена или не принадлежит компании (HTTP 400)\n- card_not_our_client — клиент не зарегистрирован в компании (HTTP 400)\n- card_user_not_found — карта не привязана к пользователю (HTTP 400)\n- gift_not_found — подарок не найден или недоступен (HTTP 400)\n- gift_type_mismatch — неверный тип подарка (нужен certificate) (HTTP 400)\n- gift_insufficient_amount — запрошено больше, чем доступно (HTTP 400)\n- gift_expiration_exceeded — срок подарка слишком короткий для акции (HTTP 400)\n- promotion_not_found — акция не найдена (HTTP 404)\n- subscription_required — нет ни подписки, ни пробного периода (HTTP 402)\n- trial_expired — пробный период закончился, подписки не было (HTTP 402)\n- subscription_inactive — подписка была, но истекла или не оплачена (HTTP 402)\n- target_config_required — не переданы настройки таргета (HTTP 400)\n- no_target_clients — по параметрам таргета нет клиентов (HTTP 400)\n- recommendation_percent_already_active — уже есть активная процентная программа (HTTP 400)\n- recommendation_gift_not_own — можно использовать только собственный подарок (HTTP 400)\n- recommendation_not_bonus_company — percent-программа только для бонусных компаний (HTTP 400)\n- recommendation_gift_expired — срок подарка недостаточен для программы (HTTP 400)\n- recommendation_not_enough_purchased — недостаточно купленных подарков (HTTP 400)\n- recommendation_cannot_change_type — нельзя изменить тип программы (HTTP 400)\n- recommendation_referrer_gift_not_found — подарок для реферала не найден (HTTP 400)\n- recommendation_gift_not_started — дата начала подарка ещё не наступила (HTTP 400)\n- recommendation_not_found — реферальная программа не найдена (HTTP 404)\n- not_found — запрашиваемый объект не найден (используется, в частности,\n  close-роутами one-time-gift/gift-for-coins/smart-ad, когда акция не найдена\n  или принадлежит другой компании) (HTTP 404)\n- business_error — операция отклонена бизнес-правилом без более специфичного\n  кода (используется, в частности, close-роутами one-time-gift/gift-for-coins/\n  smart-ad при попытке остановить уже остановленную или истёкшую акцию) (HTTP 400)\n- too_many_requests — rate-limit превышен (HTTP 429)\n- internal_error — внутренняя ошибка сервиса (HTTP 500)\n","example":"insufficient_scope"},"message":{"type":"string","description":"Человекочитаемое описание ошибки","example":"Недостаточно прав для выполнения операции."},"required":{"type":"string","description":"Требуемый scope (только для insufficient_scope)","example":"gifts:write"},"entitlement":{"type":"string","enum":["no_subscription","trial_active","trial_grace","active","grace","trial_blocked","blocked"],"description":"Состояние доступа компании (присутствует только в ответах HTTP 402).\nПоказывает, почему ключ временно не работает:\n- no_subscription — нет ни подписки, ни пробного периода;\n- trial_blocked — пробный период закончился, подписки не было;\n- blocked — подписка была, но истекла или не оплачена.\nЗначения trial_active / trial_grace / active / grace соответствуют\nрабочему состоянию ключа и в теле ошибки 402 не встречаются.\n","example":"trial_blocked"},"fields":{"type":"array","description":"Список ошибок по полям (только для validation_error)","items":{"type":"object","properties":{"field":{"type":"string","example":"giftId"},"message":{"type":"string","example":"Обязательное поле отсутствует"}}}}}},"ApiKeyError":{"$ref":"#/components/schemas/ApiV1Error"},"PromotionGiftsItem":{"type":"object","description":"Запись «разовый подарок» (one-time-gift promotion)","properties":{"id":{"type":"integer","description":"Канонический идентификатор для пути GET /promotions/one-time-gift/{id} (совпадает с promotionGiftsId). Используйте именно `id` из ответа create/list, а не promotionId.","example":501},"promotionGiftsId":{"type":"integer","example":501},"promotionId":{"type":"integer","example":200},"companyId":{"type":"integer","example":78910},"title":{"type":"string","example":"Ноябрьская акция"},"description":{"type":"string","example":"Дарим кофе всем новым клиентам"},"giftId":{"type":"integer","example":1001},"giftAmount":{"type":"integer","description":"Кол-во подарков для раздачи","example":100},"giftExpires":{"type":"integer","description":"Время жизни подарка у клиента (дни)","example":30},"giftOfferExpires":{"type":"integer","description":"Дней до того, как клиент должен открыть подарок","example":7},"cardCodes":{"type":"string","description":"Коды карт получателей (разделённые переносом строки или запятой)","example":"1234567890\n0987654321"},"statGiftsSent":{"type":"integer","example":98},"statGiftsClaimed":{"type":"integer","example":60},"statGiftsRejected":{"type":"integer","example":5},"statGiftsExpired":{"type":"integer","example":10},"statGiftsUsed":{"type":"integer","example":55},"createdAt":{"type":"integer","format":"int64","example":1720000000000},"startsAt":{"type":"integer","format":"int64","example":1720000000000},"expiredAt":{"type":"integer","format":"int64","example":1730000000000}}},"PromotionGiftsFindResponse":{"type":"object","required":["status"],"properties":{"status":{"type":"string","example":"success"},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PromotionGiftsItem"}},"rows":{"type":"integer","example":10}}}}},"PromotionGiftsGetResponse":{"type":"object","required":["status"],"properties":{"status":{"type":"string","example":"success"},"data":{"$ref":"#/components/schemas/PromotionGiftsItem"}}},"PromotionGiftsCreateRequest":{"type":"object","required":["giftId","title","description","giftAmount","giftExpires","giftOfferExpires","cardCodes"],"properties":{"giftId":{"type":"integer","description":"ID подарка из GET /api/v1/gifts (тип certificate)","example":1001},"title":{"type":"string","description":"Название акции","example":"Ноябрьская акция"},"description":{"type":"string","description":"Описание акции","example":"Дарим кофе всем новым клиентам"},"giftAmount":{"type":"integer","description":"Кол-во подарков для раздачи (≥ числа карт)","example":100},"giftExpires":{"type":"integer","description":"Время жизни подарка у клиента (дни)","example":30},"giftOfferExpires":{"type":"integer","description":"Дней до первого открытия оффера","example":7},"cardCodes":{"type":"string","description":"Коды карт получателей (каждый на новой строке или разделены запятой).\nЛимит: до 1000 карт на акцию.\n","example":"1234567890\n0987654321"}}},"PromotionGiftsCreateResponse":{"type":"object","required":["status"],"properties":{"status":{"type":"string","example":"success"},"data":{"$ref":"#/components/schemas/PromotionGiftsItem"}}},"PromocodeItem":{"type":"object","description":"Запись «подарок за покупку» (gift-for-coins / promocode)","properties":{"id":{"type":"integer","description":"Канонический идентификатор для пути GET /promotions/gift-for-coins/{id} (совпадает с promotionPromocodeId). Используйте именно `id` из ответа create/list, а не promotionId.","example":301},"promotionPromocodeId":{"type":"integer","example":301},"promotionId":{"type":"integer","example":200},"title":{"type":"string","example":"Кофе за монеты"},"description":{"type":"string","example":"Обменяй 100 монет на кофе"},"giftId":{"type":"integer","example":1001},"amount":{"type":"integer","description":"Кол-во акций (количество промокодов)","example":50},"moneySpend":{"type":"number","description":"Стоимость в монетах (coins), которую клиент должен потратить","example":100},"startedAt":{"type":"integer","format":"int64","example":1720000000000},"expiredAt":{"type":"integer","format":"int64","example":1730000000000},"moderation":{"type":"string","nullable":true,"example":"approved"},"autoActivate":{"type":"boolean","description":"Активировать автоматически при выполнении условий","example":false},"createdAt":{"type":"integer","format":"int64","example":1720000000000}}},"PromocodeFindResponse":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/PromocodeItem"}},{"$ref":"#/components/schemas/PromocodeItem"}],"description":"Список (GET /promotions/gift-for-coins) или один объект (GET /promotions/gift-for-coins/{id}).\n"},"PromocodeCreateRequest":{"type":"object","required":["title","giftId","amount","startDate","endDate","moneySpend","pictureSmall","pictureMiddle"],"properties":{"title":{"type":"string","description":"Название акции","example":"Кофе за монеты"},"description":{"type":"string","description":"Описание акции","example":"Обменяй монеты на кофе"},"giftId":{"type":"integer","description":"ID подарка из GET /api/v1/gifts","example":1001},"amount":{"type":"integer","description":"Кол-во промокодов для раздачи","example":50},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Дата начала (YYYY-MM-DD)","example":"2026-09-01"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Дата окончания (YYYY-MM-DD)","example":"2026-11-30"},"moneySpend":{"type":"number","description":"Стоимость в монетах","example":100},"pictureSmall":{"type":"string","description":"Изображение для карточки акции (квадратное, соотношение 1:1).\nПередаётся инлайном как base64 data-URI (data:image/jpeg;base64,… или\ndata:image/png;base64,…). Сервер сохраняет изображение самостоятельно.\nМаксимальный размер: 2 МБ. Обязательно при создании акции.\n","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."},"pictureMiddle":{"type":"string","description":"Изображение для описания акции (соотношение 16:10).\nПередаётся инлайном как base64 data-URI (data:image/jpeg;base64,… или\ndata:image/png;base64,…). Сервер сохраняет изображение самостоятельно.\nМаксимальный размер: 2 МБ. Обязательно при создании акции.\n","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."},"autoActivate":{"type":"boolean","description":"Активировать автоматически","example":false}}},"PromocodeCreateResponse":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["successful","error","GiftNotFound","NotEnoughGiftAmount","PromocodeIsNotVerified","GiftAfterShareTime","InvalidPromotionActivityDates"],"example":"successful"},"items":{"$ref":"#/components/schemas/PromocodeItem"}}},"SmartAdItem":{"type":"object","description":"Запись «Smart реклама» (smart-ad / target promotion, только card_code)","properties":{"id":{"type":"integer","example":401},"promotionId":{"type":"integer","example":200},"companyId":{"type":"integer","example":78910},"title":{"type":"string","example":"Персональная акция для VIP"},"description":{"type":"string","example":"Отправляем подарок выбранным картам"},"giftId":{"type":"integer","example":1001},"giftAmount":{"type":"integer","description":"Кол-во подарков","example":100},"giftExpires":{"type":"integer","description":"Время жизни подарка у клиента (дни)","example":30},"giftOfferExpires":{"type":"integer","description":"Дней до первого открытия оффера","example":7},"targetMode":{"type":"string","enum":["card_code"],"description":"Режим адресации. Через API-ключ доступен ТОЛЬКО режим card_code\n(список карт передаётся явно). Режим target_schema доступен только через ЛКБ.\n","example":"card_code"},"cardCodes":{"type":"string","description":"Коды карт получателей","example":"1234567890\n0987654321"},"createdAt":{"type":"integer","format":"int64","example":1720000000000}}},"SmartAdCreateRequest":{"type":"object","required":["title","giftId","giftAmount","giftExpires","giftOfferExpires","cardCodes","targetMode"],"properties":{"title":{"type":"string","description":"Название акции","example":"Персональная акция для VIP"},"description":{"type":"string","description":"Описание акции","example":"Отправляем подарок выбранным картам"},"giftId":{"type":"integer","description":"ID подарка (тип certificate) из GET /api/v1/gifts.\nСрок действия подарка (expiredAt) должен заканчиваться минимум на 3 дня\nПОЗЖЕ даты окончания акции — иначе ошибка gift_after_share_time.\n","example":1001},"giftAmount":{"type":"integer","description":"Кол-во подарков для раздачи (≥ числа карт)","example":100},"giftExpires":{"type":"integer","description":"Дней жизни подарка у клиента","example":30},"giftOfferExpires":{"type":"integer","description":"Дней до первого открытия оффера","example":7},"targetMode":{"type":"string","enum":["card_code"],"description":"Через API-ключ поддерживается ТОЛЬКО card_code. Любое другое\nзначение вернёт HTTP 400 с error=invalid_target_mode.\n","example":"card_code"},"cardCodes":{"type":"string","description":"Коды карт получателей (каждый на новой строке или через запятую).\nЛимит: до 1000 карт.\n","example":"1234567890\n0987654321"}}},"SmartAdFindResponse":{"type":"object","required":["items","rows"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SmartAdItem"}},"rows":{"type":"integer","example":5}}},"RecommendationPercentLevels":{"type":"object","description":"Процент вознаграждения по уровням реферальной цепочки","properties":{"1":{"type":"number","description":"Процент для уровня 1 (прямой реферал)","example":5},"2":{"type":"number","description":"Процент для уровня 2","example":3},"3":{"type":"number","description":"Процент для уровня 3","example":1}}},"RecommendationRecipientOrSender":{"type":"object","description":"Параметры подарка для получателя или реферера (один раз)","properties":{"giftId":{"type":"integer","description":"ID подарка. Срок действия подарка (expiredAt) должен заканчиваться\nминимум на 3 дня ПОЗЖЕ даты окончания программы (endDate) —\nиначе ошибка gift_after_share_time.\n","example":2001},"giftAmount":{"type":"integer","description":"Количество подарков","example":1},"expiredDays":{"type":"integer","description":"Дней жизни подарка у клиента после получения","example":30}}},"RecommendationCreatePercentRequest":{"type":"object","description":"Создание процентной акции «Рекомендации» (реферальная механика, type=percent)","required":["type","condition","giftId","levels","startDate","endDate","pictureSmall","pictureMiddle"],"properties":{"type":{"type":"string","enum":["percent"],"description":"Тип программы — процент от покупок рефералов","example":"percent"},"condition":{"type":"string","description":"Текстовое описание условия участия","example":"Приведи друга и получай 5% с каждой его покупки"},"giftId":{"type":"integer","description":"ID подарка за участие. Только собственный подарок компании.\nСрок действия подарка (expiredAt) должен заканчиваться минимум на 3 дня\nПОЗЖЕ даты окончания программы (endDate) — иначе ошибка gift_after_share_time.\nДоступно только компаниям с бонусной системой.\n","example":2001},"levels":{"$ref":"#/components/schemas/RecommendationPercentLevels"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Дата начала программы (YYYY-MM-DD)","example":"2026-09-01"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Дата окончания программы (YYYY-MM-DD). Срок подарка должен заканчиваться минимум на 3 дня позже.","example":"2027-09-01"},"pictureSmall":{"type":"string","description":"Изображение карточки программы (1:1, квадрат).\nBase64 data-URI (data:image/jpeg;base64,… или data:image/png;base64,…).\nМаксимум 2 МБ.\n","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."},"pictureMiddle":{"type":"string","description":"Изображение описания программы (16:10).\nBase64 data-URI (data:image/jpeg;base64,… или data:image/png;base64,…).\nМаксимум 2 МБ.\n","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."}}},"RecommendationCreateOnceGiftRequest":{"type":"object","description":"Создание программы «единовременный подарок» (type=once-gift)","required":["type","condition","startDate","endDate","pictureSmall","pictureMiddle","recipient","sender"],"properties":{"type":{"type":"string","enum":["once-gift"],"description":"Тип программы — единовременный подарок при выполнении условия","example":"once-gift"},"condition":{"type":"string","description":"Текстовое описание условия участия","example":"При первой покупке нового клиента оба получают подарок"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Дата начала программы (YYYY-MM-DD)","example":"2026-09-01"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Дата окончания программы (YYYY-MM-DD). Срок подарков (recipient и sender) должен заканчиваться минимум на 3 дня позже.","example":"2027-09-01"},"recipientMinBuySum":{"type":"number","description":"Минимальная сумма покупки нового клиента для активации программы","example":500},"recipient":{"$ref":"#/components/schemas/RecommendationRecipientOrSender"},"sender":{"$ref":"#/components/schemas/RecommendationRecipientOrSender"},"pictureSmall":{"type":"string","description":"Изображение карточки программы (1:1, квадрат).\nBase64 data-URI. Максимум 2 МБ.\n","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."},"pictureMiddle":{"type":"string","description":"Изображение описания программы (16:10).\nBase64 data-URI. Максимум 2 МБ.\n","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."}}},"RecommendationItem":{"type":"object","description":"Запись акции «Рекомендации» (реферальная механика)","properties":{"id":{"type":"integer","description":"Канонический идентификатор для путей GET/обновления/закрытия /promotions/recommendation/{id} (совпадает с recommendationId). Используйте именно `id` из ответа create/list, а не promotionId.","example":601},"recommendationId":{"type":"integer","example":601},"companyId":{"type":"integer","example":78910},"type":{"type":"string","enum":["percent","once-gift"],"example":"percent"},"condition":{"type":"string","example":"Приведи друга и получай бонусы"},"status":{"type":"string","description":"Статус программы (active, stopped, expired и т.п.)","example":"active"},"startDate":{"type":"string","example":"2026-09-01"},"endDate":{"type":"string","example":"2027-09-01"},"participantsCount":{"type":"integer","description":"Количество участников программы","example":42},"createdAt":{"type":"integer","format":"int64","example":1720000000000},"startedAt":{"type":"integer","format":"int64","nullable":true,"example":1720000000000},"stoppedAt":{"type":"integer","format":"int64","nullable":true,"example":null}}},"RecommendationFindResponse":{"type":"object","required":["items","rows"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RecommendationItem"}},"rows":{"type":"integer","example":5}}},"RecommendationActiveResponse":{"type":"object","required":["active"],"properties":{"active":{"type":"boolean","description":"true — у компании есть активная процентная (type=percent) акция «Рекомендации» (реферальная механика).\nМаксимум 1 активная percent-программа на компанию.\n","example":false}}}}},"paths":{"/categories":{"get":{"summary":"Справочник категорий","operationId":"getCategories","description":"Возвращает список бизнес-категорий для регистрации компании. Идемпотентен.","tags":["Регистрация"],"responses":{"200":{"description":"Список категорий","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"examples":{"success":{"summary":"Успешный ответ","value":[{"categoryId":1,"title":"Кафе и рестораны","iconUrl":"https://company.moimesta.ru/api/categories/1/icon.svg"},{"categoryId":2,"title":"Красота и здоровье","iconUrl":"https://company.moimesta.ru/api/categories/2/icon.svg"}]}}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/categories/findWithSubcatigories":{"get":{"summary":"Категории с подкатегориями","operationId":"getCategoriesWithSubcategories","description":"Возвращает категории вместе с вложенными подкатегориями.","tags":["Регистрация"],"responses":{"200":{"description":"Список категорий с подкатегориями","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CategoryWithSubcategories"}}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/checkPhone":{"get":{"summary":"Проверка телефона","operationId":"checkPhone","description":"Определяет ветку сценария регистрации по номеру телефона.\nПри companyExist=true регистрацию следует прервать и перейти к логину\nили восстановлению пароля.\n\nБИЗНЕС-ОШИБКИ возвращаются с HTTP 200 и полем errorMessage — проверяйте тело.\n","tags":["Регистрация"],"parameters":[{"name":"phone","in":"query","required":true,"description":"РФ-номер из 10 цифр без +7","schema":{"type":"integer","example":9991234567}}],"responses":{"200":{"description":"Результат проверки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckPhoneResponse"},"examples":{"newUser":{"summary":"Новый пользователь и компания (ветка A)","value":{"userExist":false,"companyExist":false}},"existingUser":{"summary":"Физлицо без компании (ветка B)","value":{"userExist":true,"companyExist":false}},"existingCompany":{"summary":"Компания уже есть (ветка C — прервать регистрацию)","value":{"userExist":true,"companyExist":true}}}}}},"400":{"description":"Некорректный phone (ошибка схемы)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/singupGetCode":{"post":{"summary":"Запрос OTP-кода","operationId":"singupGetCode","description":"Отправляет одноразовый код (OTP) на телефон через SMS, звонок или Telegram.\n\nRate-limit: 3 попытки / 10 мин на номер, 20 / 10 мин на IP, 100 / мин глобально.\n\nБИЗНЕС-ОШИБКИ возвращаются с HTTP 200 и полем errorMessage — проверяйте тело.\n","tags":["Регистрация"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendOtpRequest"},"examples":{"request":{"summary":"Запрос OTP","value":{"phone":9991234567}}}}}},"responses":{"200":{"description":"OTP отправлен или бизнес-ошибка (проверяйте errorMessage)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendOtpResponse"},"examples":{"success":{"summary":"OTP отправлен","value":{"oneTimePasswordSent":"sms","smsCodeNumber":42,"retryAfter":180}},"timeLimit":{"summary":"Бизнес-ошибка — повтор слишком рано","value":{"oneTimePasswordSent":false,"retryAfter":240,"errorMessage":"time limit"}},"companyExists":{"summary":"Бизнес-ошибка — компания уже есть","value":{"oneTimePasswordSent":false,"retryAfter":0,"errorMessage":"company Exist"}}}}}},"400":{"description":"Ошибка схемы запроса","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate-limit превышен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/singup":{"post":{"summary":"Регистрация компании","operationId":"singup","description":"Верифицирует OTP-код и создаёт компанию. При успехе возвращает токены и данные пользователя.\n\nВетка A (новый пользователь): поля username, userSurname, password обязательны.\nВетка B (существующее физлицо): username и userSurname можно опустить.\n\nБИЗНЕС-ОШИБКИ возвращаются с HTTP 200 и полем errorMessage — проверяйте тело.\n","tags":["Регистрация"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"},"examples":{"branchA":{"summary":"Ветка A — новый пользователь","value":{"phone":9991234567,"username":"Иван","userSurname":"Петров","password":"MyPass123","email":"owner@example.ru","confirmCode":"4821","companyName":"Кофейня «Утро»","categoryId":1}},"branchB":{"summary":"Ветка B — существующее физлицо","value":{"phone":9991234567,"password":"MyPass123","email":"owner@example.ru","confirmCode":"4821","companyName":"Кофейня «Утро»","categoryId":1}}}}}},"responses":{"200":{"description":"Успех или бизнес-ошибка (проверяйте errorMessage)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupResponse"},"examples":{"success":{"summary":"Компания создана","value":{"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","user":{"userId":123456,"userName":"Иван","companyId":78910,"title":"Кофейня «Утро»","balance":0,"status":{"activated":true,"isTrialPeriodActive":true}}}},"notMatch":{"summary":"Бизнес-ошибка — неверный код","value":{"errorMessage":"not match"}},"codeExpired":{"summary":"Бизнес-ошибка — код истёк","value":{"errorMessage":"code expired"}},"userDataRequired":{"summary":"Бизнес-ошибка — не переданы данные пользователя","value":{"errorMessage":"user data required"}},"invalidCompanyData":{"summary":"Бизнес-ошибка — некорректные данные компании","value":{"errorMessage":"invalid company data"}}}}}},"400":{"description":"Ошибка схемы запроса","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/restore/one-time-password":{"post":{"summary":"Запрос кода восстановления пароля","operationId":"restoreOneTimePassword","description":"Отправляет OTP для восстановления пароля. Используется, если checkPhone\nвернул companyExist=true.\n\nRate-limit: не чаще 1 раза / 1 мин на номер.\nОшибки возвращаются через HTTP 400 с деталями в поле data.\n","tags":["Восстановление пароля"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreOtpRequest"},"examples":{"request":{"summary":"Запрос кода восстановления","value":{"phone":9991234567}}}}}},"responses":{"200":{"description":"OTP для восстановления отправлен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreOtpResponse"},"examples":{"success":{"summary":"Код отправлен","value":{"oneTimePasswordSent":"sms","retryAfter":180,"smsCodeNumber":43}}}}}},"400":{"description":"Ошибка (нет компании на номере, слишком частый запрос)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreError"},"examples":{"cannotBeSended":{"summary":"Нет компании или слишком часто","value":{"status":"error","message":"","data":{"cannotBeSended":{}}}}}}}},"429":{"description":"Rate-limit превышен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/restore/change-password":{"post":{"summary":"Смена пароля по OTP","operationId":"restoreChangePassword","description":"Устанавливает новый пароль по OTP-коду из шага restore/one-time-password.\nОшибки возвращаются через HTTP 400 с деталями в поле data.\n","tags":["Восстановление пароля"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreChangePasswordRequest"},"examples":{"request":{"summary":"Смена пароля","value":{"phone":9991234567,"oneTimePassword":"4821","password":"NewPass123","confirmPassword":"NewPass123"}}}}}},"responses":{"200":{"description":"Пароль успешно изменён (тело пустое)","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Ошибка (неверный код, нет прав, пароли не совпадают)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreError"},"examples":{"invalidCode":{"summary":"Неверный OTP","value":{"status":"error","message":"","data":{"invalidOneTimePassword":{}}}},"invalidPassword":{"summary":"Пароли не совпадают","value":{"status":"error","message":"","data":{"invalidPassword":{}}}}}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth":{"post":{"summary":"Вход по паролю","operationId":"login","description":"Вход в систему по номеру телефона (как строка) и паролю.","tags":["Аутентификация"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLoginRequest"},"examples":{"request":{"summary":"Вход","value":{"username":"9991234567","password":"MyPass123"}}}}}},"responses":{"200":{"description":"Успешный вход","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthTokensResponse"}}}},"400":{"description":"Неверные учётные данные или ошибка схемы","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/access-token":{"post":{"summary":"Обмен access-токена","operationId":"exchangeAccessToken","description":"Получить обновлённый access-токен и данные пользователя по действующему access-токену.","tags":["Аутентификация"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessTokenRequest"}}}},"responses":{"200":{"description":"Новый access-токен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessTokenResponse"}}}},"400":{"description":"Невалидный токен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/refresh-token":{"post":{"summary":"Обновление токенов по refresh-токену","operationId":"refreshToken","description":"Получить новую пару access+refresh токенов по действующему refresh-токену.","tags":["Аутентификация"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenRequest"}}}},"responses":{"200":{"description":"Новые токены","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthTokensResponse"}}}},"400":{"description":"Невалидный refresh-токен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/me":{"get":{"summary":"Информация о ключе","operationId":"apiV1Me","description":"Возвращает companyId, название компании и список scope текущего ключа.\nЭндпоинт не требует дополнительных scope — доступен любому валидному ключу.\nИспользуйте для проверки ключа и обнаружения доступных возможностей.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Данные ключа","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyMeResponse"},"examples":{"success":{"summary":"Успешный ответ","value":{"companyId":78910,"companyName":"Кофейня «Утро»","scopes":["gifts:read","gifts:write","promotions:read","promotions:write","stats:read"]}}}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"},"examples":{"invalid":{"summary":"Невалидный ключ","value":{"error":"invalid_api_key"}}}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/gifts":{"get":{"summary":"Список подарков компании","operationId":"apiV1GiftsFind","description":"Возвращает список подарков компании с пагинацией.\nТребует scope: gifts:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"page","in":"query","description":"Номер страницы (начиная с 0)","schema":{"type":"integer","minimum":0,"default":0},"example":0},{"name":"limit","in":"query","description":"Количество записей на страницу (1–100)","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"example":10},{"name":"sort","in":"query","description":"Поле сортировки","schema":{"type":"string","enum":["expired_at","started_at","gift_id","title","amount"],"default":"expired_at"},"example":"expired_at"},{"name":"order","in":"query","description":"Направление сортировки","schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"example":"desc"},{"name":"search","in":"query","description":"Поиск по названию подарка","schema":{"type":"string"},"example":"кофе"}],"responses":{"200":{"description":"Список подарков","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftListResponse"}}}},"400":{"description":"Некорректные параметры (невалидный sort/order/page/limit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope gifts:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"},"examples":{"noScope":{"summary":"Нет scope","value":{"error":"insufficient_scope","required":"gifts:read"}}}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Создать подарок","operationId":"apiV1GiftsCreate","description":"Создаёт новый подарок для компании и отправляет его на модерацию.\nТребует scope: gifts:write.\ncompanyId берётся из ключа — не передавать в теле.\n\nИзображения (поле pictures) передаются инлайном как base64 data-URI\nпрямо в теле запроса — отдельного эндпоинта загрузки файлов нет.\nСервер сохраняет изображение самостоятельно.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCreateRequest"},"examples":{"certificate":{"summary":"Сертификат на 500 рублей","value":{"title":"Сертификат 500 рублей","type":"certificate","valuePrice":500,"description":"Сертификат на любой заказ","condition":"При покупке от 1000 рублей","startedAt":1720000000000,"expiredAt":1730000000000}}}}}},"responses":{"200":{"description":"Подарок создан (отправлен на модерацию)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftBase"}}}},"400":{"description":"Некорректные данные подарка","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope gifts:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/gifts/{giftId}":{"get":{"summary":"Получить подарок по ID","operationId":"apiV1GiftsGet","description":"Возвращает данные конкретного подарка компании.\nТребует scope: gifts:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"giftId","in":"path","required":true,"description":"ID подарка — поле `id` из ответа create/list (равно giftId). Подставляйте `id` из ответа, не promotionId.","schema":{"type":"integer"},"example":1001}],"responses":{"200":{"description":"Данные подарка","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftBase"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope gifts:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Обновить подарок","operationId":"apiV1GiftsUpdate","description":"Обновляет существующий подарок и отправляет на повторную модерацию.\nТребует scope: gifts:write.\ngiftId берётся строго из пути — нельзя передать в теле.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"giftId","in":"path","required":true,"description":"ID подарка для обновления — поле `id` из ответа create/list (равно giftId). Подставляйте `id` из ответа, не promotionId.","schema":{"type":"integer"},"example":1001}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCreateRequest"}}}},"responses":{"200":{"description":"Подарок обновлён","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftBase"}}}},"400":{"description":"Некорректные данные","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope gifts:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/gifts/{giftId}/stats":{"get":{"summary":"Статистика по подарку","operationId":"apiV1GiftsStats","description":"Возвращает агрегированную статистику использования подарка.\nТребует scope: stats:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"giftId","in":"path","required":true,"description":"ID подарка — поле `id` из ответа create/list (равно giftId). Подставляйте `id` из ответа, не promotionId.","schema":{"type":"integer"},"example":1001}],"responses":{"200":{"description":"Статистика по подарку","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftStatsResponse"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope stats:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/promotions/one-time-gift":{"post":{"summary":"Создать акцию «Разовый подарок»","operationId":"apiV1PromotionsOneTimeGiftCreate","description":"Создаёт акцию типа «разовый подарок» — отправляет сертификат выбранным\nдержателям карт. Требует scope: promotions:write.\n\nОграничения:\n- Подарок (giftId) должен быть типа certificate и иметь достаточное количество.\n- cardCodes — список кодов карт (каждый на новой строке или через запятую), до 1000.\n- giftAmount должен быть ≥ числа карт в cardCodes.\n- Подарок не должен истекать раньше, чем первая партия клиентов успеет его получить.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionGiftsCreateRequest"},"examples":{"create":{"summary":"Создание акции","value":{"giftId":1001,"title":"Ноябрьская акция","description":"Дарим кофе новым клиентам","giftAmount":100,"giftExpires":30,"giftOfferExpires":7,"cardCodes":"1234567890\n0987654321"}}}}}},"responses":{"200":{"description":"Акция создана","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionGiftsCreateResponse"},"examples":{"success":{"summary":"Акция создана","value":{"status":"success","data":{"promotionGiftsId":501,"title":"Ноябрьская акция"}}},"giftNotFound":{"summary":"Подарок не найден","value":{"status":"error","message":"GiftNotFound"}}}}}},"400":{"description":"Некорректные параметры","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"summary":"Список акций «Разовый подарок»","operationId":"apiV1PromotionsOneTimeGiftFind","description":"Возвращает список акций типа «разовый подарок» с пагинацией.\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":10}},{"name":"sort","in":"query","schema":{"type":"string","enum":["createdAt","expiredAt","giftAmount","giftExpires","giftOfferExpires","promotionGiftsId","promotionId","startedAt","statGiftsClaimed","statGiftsExpired","statGiftsRejected","statGiftsSent","statGiftsUsed","title"],"default":"createdAt"}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"search","in":"query","description":"Поиск по названию","schema":{"type":"string"}}],"responses":{"200":{"description":"Список акций","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionGiftsFindResponse"}}}},"400":{"description":"Некорректные параметры","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/promotions/one-time-gift/{id}":{"get":{"summary":"Получить акцию «Разовый подарок» по ID","operationId":"apiV1PromotionsOneTimeGiftGet","description":"Возвращает данные конкретной акции «разовый подарок».\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции — поле `id` из ответа create/list (равно promotionGiftsId). Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":501}],"responses":{"200":{"description":"Данные акции","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionGiftsGetResponse"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/promotions/one-time-gift/{id}/close":{"post":{"summary":"Закрыть акцию «Разовый подарок»","operationId":"apiV1PromotionsOneTimeGiftClose","description":"Досрочно останавливает акцию «разовый подарок» (архивирует акцию — дата\nокончания переносится на вчерашний день, дальнейшая раздача подарка\nпрекращается). Требует scope: promotions:write.\n\nИЗВЕСТНОЕ ОГРАНИЧЕНИЕ: для акций этого типа метод сейчас не может\nфактически остановить акцию и при любом вызове отвечает HTTP 400\n(business_error), независимо от параметров запроса или состояния акции.\nОтвет 200 ниже описан как часть контракта, но фактически недостижим до\nустранения этого ограничения.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции — поле `id` из ответа create/list (равно promotionGiftsId). Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":501}],"responses":{"200":{"description":"Акция остановлена. Фактически недостижимо для акций этого типа — см. известное ограничение в описании метода выше.","content":{"application/json":{"schema":{"type":"string","example":"OK"}}}},"400":{"description":"Акцию не удалось остановить. Для акций этого типа это единственный фактический результат вызова (см. известное ограничение выше) — возвращается независимо от того, активна акция, уже остановлена или её период истёк.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"cannotStop":{"summary":"Акцию не удалось остановить (текущее ограничение метода)","value":{"error":"business_error","message":"Не удалось выполнить операцию, проверьте параметры и попробуйте ещё раз."}}}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"404":{"description":"Акция не найдена или принадлежит другой компании","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}},"/v1/promotions/gift-for-coins":{"post":{"summary":"Создать акцию «Подарок за покупку»","operationId":"apiV1PromotionsGiftForCoinsCreate","description":"Создаёт акцию типа «подарок за покупку» (promocode) — клиент тратит\nнакопленные монеты и получает подарок.\nТребует scope: promotions:write.\n\nПоля pictureSmall и pictureMiddle обязательны при создании и передаются\nинлайном как base64 data-URI. Сервер сохраняет изображения самостоятельно.\n\nВ личном кабинете компании эта механика называется «Подарок за покупку».\nОтдельный раздел ЛКБ «Подарок за монеты» (обмен накопленных монет клиента\nна подарок) — другая механика и через /api/v1 недоступен.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromocodeCreateRequest"},"examples":{"create":{"summary":"Создание акции","value":{"title":"Кофе за монеты","description":"Обменяй 100 монет на любой кофе","giftId":1001,"amount":50,"startDate":"2026-09-01","endDate":"2026-11-30","moneySpend":100}}}}}},"responses":{"200":{"description":"Результат создания акции","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromocodeCreateResponse"},"examples":{"success":{"summary":"Акция создана","value":{"status":"successful"}},"giftNotFound":{"summary":"Подарок не найден","value":{"status":"GiftNotFound"}}}}}},"400":{"description":"Некорректные параметры","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"summary":"Список акций «Подарок за покупку»","operationId":"apiV1PromotionsGiftForCoinsFind","description":"Возвращает список акций типа «подарок за покупку» с пагинацией.\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":10}},{"name":"sort","in":"query","schema":{"type":"string","enum":["company_id","expiredAt","startedAt","title"],"default":"expiredAt"}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"search","in":"query","description":"Поиск по названию","schema":{"type":"string"}}],"responses":{"200":{"description":"Список акций","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromocodeFindResponse"}}}},"400":{"description":"Некорректные параметры","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/promotions/gift-for-coins/{id}":{"get":{"summary":"Получить акцию «Подарок за покупку» по ID","operationId":"apiV1PromotionsGiftForCoinsGet","description":"Возвращает данные конкретной акции «подарок за покупку».\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции — поле `id` из ответа create/list (равно promotionPromocodeId). Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":301}],"responses":{"200":{"description":"Данные акции","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromocodeFindResponse"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyError"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/promotions/gift-for-coins/{id}/close":{"post":{"summary":"Закрыть акцию «Подарок за покупку»","operationId":"apiV1PromotionsGiftForCoinsClose","description":"Досрочно останавливает акцию «подарок за покупку» (архивирует акцию — дата\nокончания переносится на вчерашний день, промокод перестаёт выдаваться).\nТребует scope: promotions:write.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции — поле `id` из ответа create/list (равно promotionPromocodeId). Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":301}],"responses":{"200":{"description":"Акция остановлена","content":{"application/json":{"schema":{"type":"string","example":"OK"}}}},"400":{"description":"Акцию нельзя остановить — она уже остановлена или её период уже истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"alreadyStopped":{"summary":"Акция уже остановлена/истекла","value":{"error":"business_error","message":"Не удалось выполнить операцию, проверьте параметры и попробуйте ещё раз."}}}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"404":{"description":"Акция не найдена или принадлежит другой компании","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}},"/v1/promotions/smart-ad":{"post":{"summary":"Создать акцию «Smart реклама»","operationId":"apiV1PromotionsSmartAdCreate","description":"Создаёт акцию типа «Smart реклама» (target promotion) — отправляет сертификат\nконкретным держателям карт по списку кодов. Требует scope: promotions:write.\n\nОГРАНИЧЕНИЕ: через API-ключ поддерживается ТОЛЬКО targetMode=card_code.\nЛюбое другое значение вернёт HTTP 400 (error=invalid_target_mode).\nРежим target_schema (автовыборка по профилю клиента) доступен только через ЛКБ.\n\nПРАВИЛО ДАТ ПОДАРКА: срок действия подарка (expiredAt) должен заканчиваться\nминимум на 3 дня ПОЗЖЕ даты окончания акции — иначе ошибка gift_after_share_time.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmartAdCreateRequest"},"examples":{"create":{"summary":"Создание Smart рекламы","value":{"title":"Персональная акция для VIP","description":"Персональный подарок для постоянных клиентов","giftId":1001,"giftAmount":10,"giftExpires":30,"giftOfferExpires":7,"targetMode":"card_code","cardCodes":"1234567890\n0987654321"}}}}}},"responses":{"200":{"description":"Акция создана","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmartAdItem"}}}},"400":{"description":"Некорректные параметры или неподдерживаемый targetMode","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"invalidTargetMode":{"summary":"Неподдерживаемый targetMode","value":{"error":"invalid_target_mode","message":"Через API-ключ поддерживается только режим targetMode=card_code."}},"giftAfterShareTime":{"summary":"Срок подарка не перекрывает акцию + 3 дня","value":{"error":"gift_after_share_time","message":"Подарок должен действовать минимум на 3 дня дольше даты окончания акции."}}}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}},"get":{"summary":"Список акций «Smart реклама»","operationId":"apiV1PromotionsSmartAdFind","description":"Возвращает список акций типа «Smart реклама» с пагинацией.\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":10}},{"name":"sort","in":"query","schema":{"type":"string","enum":["createdAt","giftAmount","title"],"default":"createdAt"}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"search","in":"query","description":"Поиск по названию","schema":{"type":"string"}}],"responses":{"200":{"description":"Список акций Smart рекламы","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmartAdFindResponse"}}}},"400":{"description":"Некорректные параметры","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}},"/v1/promotions/smart-ad/{id}":{"get":{"summary":"Получить акцию «Smart реклама» по ID","operationId":"apiV1PromotionsSmartAdGet","description":"Возвращает данные конкретной акции «Smart реклама».\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции — поле `id` из ответа create/list. Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":401}],"responses":{"200":{"description":"Данные акции","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmartAdItem"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"404":{"description":"Акция не найдена","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}},"/v1/promotions/smart-ad/{id}/close":{"post":{"summary":"Закрыть акцию «Smart реклама»","operationId":"apiV1PromotionsSmartAdClose","description":"Досрочно останавливает акцию «Smart реклама» (архивирует акцию — дата\nокончания переносится на вчерашний день, дальнейшая раздача подарка\nпрекращается). Требует scope: promotions:write.\n\nИЗВЕСТНОЕ ОГРАНИЧЕНИЕ: для акций этого типа метод сейчас не может\nфактически остановить акцию и при любом вызове отвечает HTTP 400\n(business_error), независимо от параметров запроса или состояния акции.\nОтвет 200 ниже описан как часть контракта, но фактически недостижим до\nустранения этого ограничения.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции — поле `id` из ответа create/list (равно promotionTargetId). Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":401}],"responses":{"200":{"description":"Акция остановлена. Фактически недостижимо для акций этого типа — см. известное ограничение в описании метода выше.","content":{"application/json":{"schema":{"type":"string","example":"OK"}}}},"400":{"description":"Акцию не удалось остановить. Для акций этого типа это единственный фактический результат вызова (см. известное ограничение выше) — возвращается независимо от того, активна акция, уже остановлена или её период истёк.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"cannotStop":{"summary":"Акцию не удалось остановить (текущее ограничение метода)","value":{"error":"business_error","message":"Не удалось выполнить операцию, проверьте параметры и попробуйте ещё раз."}}}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"404":{"description":"Акция не найдена или принадлежит другой компании","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}},"/v1/promotions/recommendation/active":{"get":{"summary":"Проверить наличие активной процентной программы","operationId":"apiV1PromotionsRecommendationActive","description":"Возвращает {active: boolean} — есть ли у компании активная процентная (type=percent)\nакция «Рекомендации» (реферальная механика). Максимум 1 активная percent-акция на компанию одновременно.\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Статус наличия активной процентной программы","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationActiveResponse"},"examples":{"noActive":{"summary":"Нет активной","value":{"active":false}},"hasActive":{"summary":"Есть активная","value":{"active":true}}}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}},"/v1/promotions/recommendation":{"post":{"summary":"Создать акцию «Рекомендации»","operationId":"apiV1PromotionsRecommendationCreate","description":"Создаёт акцию «Рекомендации» (реферальная механика) компании. Два типа:\n- type=percent — процент от покупок рефералов; только для компаний с бонусной системой;\n  максимум 1 активная percent-программа на компанию (проверить через /active).\n- type=once-gift — единовременный подарок рефереру и/или новому клиенту при первой покупке.\n\nТребует scope: promotions:write.\n\nПРАВИЛО ДАТ ПОДАРКА: срок действия подарков (expiredAt) должен заканчиваться\nминимум на 3 дня ПОЗЖЕ даты окончания программы (endDate) — иначе ошибка gift_after_share_time.\n\nИзображения pictureSmall и pictureMiddle передаются инлайном как base64 data-URI.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RecommendationCreatePercentRequest"},{"$ref":"#/components/schemas/RecommendationCreateOnceGiftRequest"}],"discriminator":{"propertyName":"type"}},"examples":{"percent":{"summary":"Процентная программа","value":{"type":"percent","condition":"Приведи друга и получай 5% с каждой его покупки","giftId":2001,"levels":{"1":5,"2":3,"3":1},"startDate":"2026-09-01","endDate":"2027-09-01","pictureSmall":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB...","pictureMiddle":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."}},"onceGift":{"summary":"Единовременный подарок","value":{"type":"once-gift","condition":"При первой покупке нового клиента оба получают подарок","startDate":"2026-09-01","endDate":"2027-09-01","recipientMinBuySum":500,"recipient":{"giftId":2002,"giftAmount":1,"expiredDays":30},"sender":{"giftId":2003,"giftAmount":1,"expiredDays":30},"pictureSmall":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB...","pictureMiddle":"data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."}}}}}},"responses":{"200":{"description":"Программа создана","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationItem"}}}},"400":{"description":"Некорректные параметры или бизнес-ошибка","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"percentAlreadyActive":{"summary":"Уже есть активная процентная программа","value":{"error":"recommendation_percent_already_active","message":"У компании уже есть активная процентная реферальная программа. Завершите текущую перед созданием новой."}},"giftAfterShareTime":{"summary":"Срок подарка не перекрывает программу + 3 дня","value":{"error":"gift_after_share_time","message":"Подарок должен действовать минимум на 3 дня дольше даты окончания акции."}},"notBonusCompany":{"summary":"Компания без бонусной системы","value":{"error":"recommendation_not_bonus_company","message":"Процентная реферальная программа доступна только компаниям с бонусной системой."}}}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}},"get":{"summary":"Список акций «Рекомендации»","operationId":"apiV1PromotionsRecommendationFind","description":"Возвращает список акций «Рекомендации» компании с пагинацией.\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":10}},{"name":"sort","in":"query","schema":{"type":"string","enum":["endDate","expiredAt","gift","participantsCount","recommendationId","startDate","startedAt","status","stoppedAt","type"],"default":"recommendationId"}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":{"200":{"description":"Список программ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationFindResponse"}}}},"400":{"description":"Некорректные параметры","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}},"/v1/promotions/recommendation/{id}":{"post":{"summary":"Обновить акцию «Рекомендации»","operationId":"apiV1PromotionsRecommendationUpdate","description":"Обновляет параметры акции «Рекомендации». ID берётся из пути — нельзя передать в теле.\nТип программы (type) изменить нельзя — ошибка recommendation_cannot_change_type.\nТребует scope: promotions:write.\n\nПРАВИЛО ДАТ ПОДАРКА: срок действия подарков должен заканчиваться минимум\nна 3 дня ПОЗЖЕ обновлённой даты окончания программы (endDate).\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции «Рекомендации» — поле `id` из ответа create/list (равно recommendationId). Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":601}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RecommendationCreatePercentRequest"},{"$ref":"#/components/schemas/RecommendationCreateOnceGiftRequest"}],"discriminator":{"propertyName":"type"}}}}},"responses":{"200":{"description":"Программа обновлена","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationItem"}}}},"400":{"description":"Некорректные параметры или бизнес-ошибка","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"cannotChangeType":{"summary":"Нельзя изменить тип программы","value":{"error":"recommendation_cannot_change_type","message":"Нельзя изменить тип уже созданной программы."}}}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"404":{"description":"Программа не найдена","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}},"get":{"summary":"Получить акцию «Рекомендации» по ID","operationId":"apiV1PromotionsRecommendationGet","description":"Возвращает данные конкретной акции «Рекомендации».\nТребует scope: promotions:read.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции «Рекомендации» — поле `id` из ответа create/list (равно recommendationId). Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":601}],"responses":{"200":{"description":"Данные программы","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationItem"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"404":{"description":"Программа не найдена","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}},"/v1/promotions/recommendation/{id}/close":{"post":{"summary":"Закрыть акцию «Рекомендации»","operationId":"apiV1PromotionsRecommendationClose","description":"Досрочно завершает акцию «Рекомендации». Требует scope: promotions:write.\n\nМЕТОД ИДЕМПОТЕНТЕН И НЕ СООБЩАЕТ, БЫЛО ЛИ РЕАЛЬНОЕ ИЗМЕНЕНИЕ: отвечает\nHTTP 200 даже если акция с указанным `id` не найдена, принадлежит другой\nкомпании или уже была закрыта ранее. Успешный ответ подтверждает только\nто, что запрос принят и обработан — не то, что состояние акции\nизменилось. Проверяйте фактический статус акции через GET по тому же id.\n","tags":["Company Management API"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID акции «Рекомендации» — поле `id` из ответа create/list (равно recommendationId). Используйте `id`, а не promotionId.","schema":{"type":"integer"},"example":601}],"responses":{"200":{"description":"Запрос принят и обработан (не гарантирует, что акция реально была найдена/закрыта — см. описание метода выше).","content":{"application/json":{"schema":{"type":"string","example":"OK"}}}},"401":{"description":"API-ключ отсутствует, невалиден или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"402":{"description":"Ключ неактивен — нет активного пробного периода или оплаченной подписки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"},"examples":{"subscriptionRequired":{"summary":"Нет ни подписки, ни пробного периода","value":{"error":"subscription_required","message":"API-ключи работают только при активном пробном периоде или оплаченной подписке. Активируйте пробный период или оформите подписку.","entitlement":"no_subscription"}},"trialExpired":{"summary":"Пробный период закончился","value":{"error":"trial_expired","message":"Пробный период закончился. Оформите подписку, чтобы возобновить работу API-ключей.","entitlement":"trial_blocked"}},"subscriptionInactive":{"summary":"Подписка истекла или не оплачена","value":{"error":"subscription_inactive","message":"Подписка неактивна. Оплатите, чтобы возобновить работу API-ключей.","entitlement":"blocked"}}}}}},"403":{"description":"Недостаточно прав (требуется scope promotions:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}},"500":{"description":"Сбой сервера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiV1Error"}}}}}}}}}