Endpoint: Создание промокода Stripe для существующих продуктов
Зачем это нужно
EasyPay позволяет создавать процентные промокоды Stripe (Coupon + Promotion Code) и привязывать их сразу к 1..N вашим уже одобренным продуктам — одним запросом. Промокод — это текст, который клиент вводит на чекауте Stripe (например, BLACKFRIDAY, SUMMER25), чтобы получить процентную скидку на конкретные продукты.
Используйте этот API когда:
хотите запустить рекламную кампанию с промокодом на несколько ваших продуктов разом (например, скидка 20% на «Pro plan» и «Pro Annual» одновременно);
партнёрский маркетолог хочет выпускать промокоды самостоятельно, не дёргая команду заботы;
AI-агент партнёра должен оформить промокод по запросу клиента прямо в чате (через MCP).
Запрос идемпотентный: повторите с тем же idempotency_key и тем же телом — вернётся тот же промокод, без дублей в Stripe.
MVP — только процентная скидка (percent_off). Фиксированная сумма (amount_off) — в будущей версии.
Internal beta. Сохраняйте code, stripe_coupon_id и stripe_promotion_code_id из ответа на своей стороне — это рабочие идентификаторы промокода для дальнейшего использования. Отдельная ручка для деактивации промокода (deactivate_partner_stripe_promotion_code) появится позже.
Как подключиться
Запросите API-ключ у вашего менеджера EasyPay — или скопируйте его из мини-апп («Show key» на первом шаге онбординга).
Менеджер активирует разрешение
product_createдля вашего аккаунта (тот же permission, что и для создания продукта / Payment Link — отдельного не нужно).Узнайте
stripe_product_idнужных одобренных продуктов — они есть в мини-апп в карточках продуктов или в вашей Internal Tariffs Google-таблице. Все привязываемые продукты должны принадлежать вам и быть одного окружения (все live ИЛИ все test) — смешанный список вернётmixed_environment.
Endpoint
POST https://n8n.thenextgen.store/webhook/promotion-code-create
X-Partner-Api-Key: ваш-api-ключ
Content-Type: application/jsonКлюч передаётся в header
X-Partner-Api-Key— это unified стандарт EasyPay для MCP-совместимых ручек. Для совместимости с legacy-клиентами полеapi_keyв теле тоже поддерживается, но header — рекомендуемый способ.
Формат запроса
{
"stripe_product_ids": ["prod_XXXXXXXXXXXX", "prod_YYYYYYYYYYYY"],
"code": "BLACKFRIDAY",
"percent_off": 25,
"duration": "once",
"max_redemptions": 100,
"expires_at": "2026-12-01T00:00:00Z",
"idempotency_key": "ваш-уникальный-ключ-этого-запроса"
}Параметры:
Параметр | Обязательный | Описание |
|---|---|---|
| Да | Массив из 1..50 ID одобренных продуктов партнёра в Stripe ( |
| Да | Текст, который клиент введёт на чекауте Stripe (1..500 символов; разрешены |
| Да | Размер скидки в процентах. Целое число 1..100. |
| Нет | Длительность скидки Stripe Coupon. Возможные значения: |
| Только если | Целое число ≥1. Сколько месяцев действует скидка для |
| Нет | Максимальное число использований промокода всеми клиентами суммарно. Целое ≥1. Не передавайте — без лимита. |
| Нет | Дата и время в ISO8601, когда Stripe перестанет принимать промокод на чекауте. Должно быть минимум 60 секунд в будущем. Не передавайте — без срока. |
| Да | Партнёрский уникальный ключ запроса (1..128 символов). Один и тот же ключ + то же тело = безопасный replay. НЕ должен начинаться с |
| Нет | Идентификатор источника для аналитики ( |
Что наследуется от продуктов (нельзя переопределить): is_test — все продукты должны быть одного окружения, оно и определяет, будет ли промокод создан в Stripe test mode или live mode.
Формат ответа
Успешный ответ (200)
{
"success": true,
"stripe_coupon_id": "AB12CD34",
"stripe_promotion_code_id": "promo_1ABCDEF...",
"code": "BLACKFRIDAY",
"percent_off": 25,
"duration": "once",
"duration_in_months": null,
"max_redemptions": 100,
"expires_at": "2026-12-01T00:00:00Z",
"stripe_product_ids": ["prod_XXXXXXXXXXXX", "prod_YYYYYYYYYYYY"],
"is_test": false,
"idempotency_key": "ваш-уникальный-ключ-этого-запроса",
"created_at": "2026-05-13T16:41:20.096Z",
"is_replay": false,
"is_retry": false,
"retry_count": 0
}Поле | Описание |
|---|---|
| Финальный (нормализованный к верхнему регистру) текст промокода, который клиент вводит на чекауте. На случай разницы регистров отдавайте клиенту именно это значение. |
| ID Stripe Coupon — внутренний объект скидки в Stripe. Может пригодиться для сверки в Stripe Dashboard или будущей деактивации. |
| ID Stripe Promotion Code ( |
|
|
|
|
|
|
| Сколько внутренних retry-попыток было сделано до успеха ( |
| UTC-таймстамп первоначального создания row в EasyPay (не Stripe). На replay не меняется. |
Ошибки
Все ошибки возвращаются с HTTP 200 + полем success: false — это нужно, чтобы AI-агенты и n8n-флоу не путали клиентскую ошибку с сетевым сбоем.
| Когда срабатывает |
|---|---|
| Невалидное тело запроса: пропущенные поля, |
| Невалидный API-ключ или партнёр-аккаунт неактивен |
| У партнёра нет разрешения |
| Один из |
| Один из продуктов ещё не прошёл модерацию (нет |
| У продукта повреждены данные в Internal Tariffs — обратитесь в команду заботы. |
| Переданы |
| Текст промокода уже занят на вашем Stripe-аккаунте. Возьмите более уникальный (например, с префиксом бренда). |
| Тот же |
| Сбой на стороне Stripe (4xx — детали в |
| Сбой EasyPay. Безопасно повторить запрос с тем же |
Идемпотентность и повторы
Сервис рассчитан на безопасные повторы.
Тот же
**idempotency_key**+ то же тело запроса. Возвращается тот же промокод. В ответеis_replay: true. Никаких дублей в Stripe. Лимит на 24 часа — после этого та же комбинация ключ+тело может создать новый промокод.Тот же
**idempotency_key**+ другое тело. Возвращаетсяidempotency_conflict. Никаких изменений в Stripe. Сгенерируйте новый ключ для нового тела.Сетевой сбой посреди обработки (вы не получили ответ). Повторите с тем же ключом и телом — EasyPay подхватит работу с того места, где она прервалась.
Лимит ретраев. На один
idempotency_keyдопустимо 5 неудачных попыток. После шестой ключ блокируется какfailed_terminal— следующие запросы вернут закэшированную ошибку. Чтобы повторить — сгенерируйте новыйidempotency_key.
Привязка к нескольким продуктам
Промокод применяется на чекауте только к тем продуктам, чьи prod_* перечислены в stripe_product_ids. Например, если у вас три продукта (Basic, Pro, Enterprise) и вы создали промокод с stripe_product_ids: ["prod_Pro", "prod_Enterprise"], то клиент введёт код только при покупке Pro или Enterprise — на Basic он не сработает.
Это удобно для маркетинговых акций «скидка на премиум-планы» без необходимости создавать отдельный промокод под каждый продукт.
Ограничения
Endpoint доступен только для уже одобренных продуктов партнёра. Для нового продукта сначала проведите его через мини-апп (модерация).
1..50 продуктов в одном промокоде.
codeдолжен быть уникальным в рамках вашего Stripe-аккаунта.idempotency_key1..128 символов, не начинается сingest:.Все привязываемые продукты — одного окружения (test ИЛИ live).
Сохраняйте
codeиstripe_promotion_code_idна своей стороне сразу после создания промокода.Деактивация — через будущую ручку
deactivate_partner_stripe_promotion_code(пока — через команду заботы EasyPay).MVP: только
percent_off. Фиксированной суммы (amount_off), бесплатной доставки, currency restrictions — пока нет.
Пример на Python
import urllib.request
import json
import uuid
url = "https://n8n.thenextgen.store/webhook/promotion-code-create"
payload = {
"stripe_product_ids": ["prod_XXXXXXXXXXXX", "prod_YYYYYYYYYYYY"],
"code": "BLACKFRIDAY",
"percent_off": 25,
"duration": "once",
"max_redemptions": 100,
"expires_at": "2026-12-01T00:00:00Z",
"idempotency_key": str(uuid.uuid4())
}
req = urllib.request.Request(
url,
data=json.dumps(payload).encode("utf-8"),
headers={
"X-Partner-Api-Key": "ваш-api-ключ",
"Content-Type": "application/json",
},
method="POST",
)
with urllib.request.urlopen(req) as resp:
result = json.loads(resp.read().decode("utf-8"))
if result.get("success"):
print(f"Promo code to share with customers: {result['code']}")
print(f"Stripe promo id: {result['stripe_promotion_code_id']}")
print(f"is_replay: {result.get('is_replay')}")
else:
print(f"Error: {result.get('error_code')} — {result.get('error_message')}")Пример на cURL
curl -X POST https://n8n.thenextgen.store/webhook/promotion-code-create \
-H "X-Partner-Api-Key: ваш-api-ключ" \
-H "Content-Type: application/json" \
-d '{
"stripe_product_ids": ["prod_XXXXXXXXXXXX"],
"code": "SUMMER25",
"percent_off": 25,
"duration": "once",
"idempotency_key": "summer-2026-promo-001"
}'Подписки: пример с длительной скидкой
Для продуктов-подписок промокод может действовать несколько биллинг-циклов:
{
"stripe_product_ids": ["prod_SUBSCRIPTION_PRODUCT_ID"],
"code": "FIRST3MONTHS",
"percent_off": 50,
"duration": "repeating",
"duration_in_months": 3,
"max_redemptions": 200,
"idempotency_key": "summer-2026-3mo-discount"
}С таким промокодом первые 3 ежемесячных списания будут со скидкой 50%; дальше — полная цена.
Через MCP-агента
Если у вас подключён EasyPay MCP-сервер (см. статью про MCP), можно создать промокод одной фразой в чате:
Создай промокод BLACKFRIDAY со скидкой 25% на продукты prod_XXX и prod_YYY,
лимит 100 использований, до 1 декабря.Агент сам соберёт payload и вызовет create_partner_stripe_promotion_code. Ключ передаётся транспортно через MCP-config — модель его не видит.
Если что-то пошло не так
**unauthorized**— обновите ключ через мини-апп («Show again» на первом шаге онбординга или у вашего менеджера).**product_not_found**для продукта, который вы видите в мини-апп — проверьте, что копируете именноstripe_product_id(форматprod_…), а не внутренний номер из Internal Tariffs. И что окружение совпадает.**mixed_environment**— разбейте запрос на два: отдельный для test-продуктов, отдельный для live.**code_already_exists**— текст уже занят. Возьмите более уникальный (например, добавьте префикс с названием бренда:MYBRAND-BLACKFRIDAY).**idempotency_conflict**— сгенерируйте новый ключ. Не пытайтесь «починить» существующий: каждое тело запроса должно иметь свой ключ.**invalid_input**с сообщением про reserved prefix —idempotency_keyне должен начинаться сingest:. Сгенерируйте новый ключ (например,uuid.uuid4()).Любая другая ситуация — напишите в вашу EasyPay-группу с командой заботы или попросите MCP-агента передать запрос команде заботы.