Endpoint: Создание Payment Link для существующего продукта
Зачем это нужно
EasyPay создаёт первую платёжную ссылку через мини-апп с модерацией — проверив, что описание продукта соответствует требованиям Stripe.
Этот API нужен, когда продукт уже одобрен и первая платёжная ссылка на него работает, а вам понадобилась ещё одна ссылка к нему: с другой ценой, другой валютой (USD/EUR/GBP/BRL), другим набором способов оплаты, или другим success_url для отдельной воронки. Повторно проходить модерацию не нужно — ручка переиспользует параметры уже одобренного продукта (тип, интервал подписки, тестовый/боевой режим) и создаёт только новый Stripe Price + Payment Link. Валюту можно либо унаследовать от продукта (по умолчанию), либо передать явно через price.currency.
Запрос идемпотентный: если повторить с тем же idempotency_key и тем же телом — вернётся та же ссылка, без дублей. Если тело отличается — вернётся ошибка idempotency_conflict.
Internal beta. Сохраняйте short_url из ответа на своей стороне — это рабочая ссылка, которую вы дальше используете и отдаёте клиенту.
Как подключиться
Запросите API-ключ у вашего менеджера EasyPay — или скопируйте его из мини-апп («Show key» на первом шаге онбординга).
Менеджер активирует разрешение
product_createдля вашего аккаунта (тот же permission, что и для создания продукта через мини-апп — отдельного разрешения не нужно).Узнайте
stripe_product_idнужного одобренного продукта — он есть в мини-апп в карточке продукта или в вашей Internal Tariffs Google-таблице.
Endpoint
POST https://n8n.thenextgen.store/webhook/payment-link-create
Content-Type: application/jsonФормат запроса
{
"auth_mode": "api_key",
"api_key": "ваш-api-ключ",
"stripe_product_id": "prod_XXXXXXXXXXXX",
"price": {
"unit_amount": 9900,
"currency": "EUR",
"interval_count": 1,
"trial_days": 0
},
"payment_link": {
"payment_method_types": ["card", "link"],
"allow_promotion_codes": false,
"success_url": "https://example.com/thanks",
"quantity": 1
},
"idempotency_key": "ваш-уникальный-ключ-этого-запроса"
}Параметры:
Параметр | Обязательный | Описание |
|---|---|---|
| Да | Всегда |
| Да | API-ключ партнёра (UUID) |
| Да | ID одобренного продукта партнёра в Stripe ( |
| Да | Цена в наименьшей единице валюты, целое положительное (для USD/EUR/GBP/BRL — сотые доли; |
| Нет | Валюта Price: |
| Нет (только для подписок) | Сколько интервалов между списаниями: |
| Нет (только для подписок) | Длина бесплатного триала в днях. По умолчанию |
| Нет | Массив способов оплаты для этой конкретной ссылки. Если не указан — Stripe покажет дефолтный набор продукта. Значения проверяются: неподключённый или несовместимый с валютой способ вернёт |
| Нет | Разрешить ли вводить промокод на чекауте. По умолчанию |
| Нет | HTTPS-URL, куда перенаправить клиента после успешной оплаты. Максимум 2048 символов. Если не указан — Stripe покажет свою страницу успеха. |
| Нет | Количество единиц продукта в чекауте. По умолчанию |
| Рекомендуется | Любая строка до 128 символов. Если не передать — сервер сгенерирует UUID и вернёт его в ответе. Передавайте свой ключ, если хотите безопасный retry. НЕ должен начинаться с |
Что наследуется от продукта (нельзя переопределить в этом запросе): тип (one_time / subscription), интервал подписки (month / year / …), тестовый/боевой режим. Валюта наследуется по умолчанию, но её можно явно переопределить через price.currency. Если нужно поменять тип или интервал — создайте отдельный продукт через стандартный flow в мини-апп.
Способы оплаты. Проверенные и работающие: card, link (обе — под USD, EUR, GBP, BRL), sepa_debit (только EUR), pix (только BRL), us_bank_account (только USD).
Два способа не подключены в Stripe-аккаунте EasyPay и отклоняются с ошибкой invalid_input: zip и bacs_debit. Если они вам нужны — напишите команде заботы EasyPay, это включается на нашей стороне.
Остальные способы Stripe (cashapp, alipay, wechat_pay, klarna, afterpay_clearpay, affirm и любые новые) передавайте, если нужны: мы их не блокируем, но и не обещаем — совместимость определяет Stripe. Если Stripe откажет в каком-то из них, ссылка всё равно будет создана — без этого способа, и вы получите об этом отдельное уведомление.
Способ, несовместимый с валютой ссылки, отклоняется с invalid_input и текстом, называющим и способ, и валюту (например, klarna работает у нас только с USD). При override валюты совместимость проверяется по новой валюте. Проверка идёт до обращения в Stripe — без побочных эффектов.
Формат ответа
Успешный ответ (200)
{
"success": true,
"stripe_product_id": "prod_XXXXXXXXXXXX",
"stripe_price_id": "price_YYYYYYYYYYYY",
"stripe_payment_link_id": "plink_ZZZZZZZZZZZZ",
"short_url": "https://short.appsign.me/abc",
"short_url_id": "lnk_5hfk_...",
"currency": "EUR",
"currency_source": "overridden",
"unit_amount": 9900,
"type": "one_time",
"is_test": false,
"idempotency_key": "ваш-уникальный-ключ-этого-запроса",
"is_replay": false,
"retry_count": 0
}Поле | Описание |
|---|---|
| Короткая ссылка (через short.io, домен |
| ID короткой ссылки в short.io — пригодится если в будущем понадобится её удалить или обновить. |
| Идентификаторы объектов в Stripe (не URL), для сверки в Stripe Dashboard и операций отмены/возврата. Полный Stripe URL не возвращается партнёру — он остаётся внутренней деталью EasyPay. |
| Эффективная валюта Price: либо переданная партнёром через |
| Источник валюты: |
|
|
| Тот же ключ, что вы передали (или сгенерированный сервером, если не передавали). |
| Сколько раз пришлось повторить попытку до успеха ( |
Ошибки
Все ошибки возвращаются с HTTP 200 + полем success: false. Это нужно, чтобы Telegram-боты, n8n-флоу и MCP-агенты не путали клиентскую ошибку с сетевым сбоем.
| Когда срабатывает |
|---|---|
| Невалидное тело запроса: пропущенные поля, отрицательная сумма, неверный формат, |
| Невалидный API-ключ |
| У партнёра нет разрешения |
|
|
| Продукт ещё не прошёл модерацию (нет |
| В Internal Tariffs у продукта повреждены данные — обратитесь в команду заботы EasyPay |
| Передан способ, не подключённый у EasyPay ( |
| Тот же |
| Stripe Payment Link создан, но short.io временно недоступен — короткой ссылки нет. См. секцию ниже. |
| Сбой на стороне Stripe (4xx — детали в |
| Сбой EasyPay. Безопасно повторить запрос с тем же |
Короткая ссылка (short_url)
Каждая успешная Payment Link автоматически получает короткий алиас через short.io (тот же сервис, который генерирует ссылки в основном flow создания продуктов через мини-апп). Короткая ссылка живёт на домене short.appsign.me и указывает на полный Stripe URL внутри EasyPay. Партнёр только её и видит — полный Stripe URL вам не возвращается.
Поведение:
Создаётся всегда — и в live, и в test режиме (тест-продукты получают рабочую короткую ссылку).
Создаётся один раз — на первой успешной попытке. На повторах с тем же
idempotency_key(replay, resume) возвращается тот жеshort_url— мы не пересоздаём её.Hard-fail при недоступности short.io. Если short.io не отвечает после трёх попыток в рамках одного запроса, ответ будет
success: falseсerror_code: 'short_url_unavailable'. Stripe Payment Link при этом создан (мы его не теряем), но партнёр-смотрящего URL у вас нет. Повторный запрос с тем жеidempotency_keyвернёт ту же ошибку, не дёргая ни Stripe, ни short.io — пока команда заботы EasyPay вручную не доcоздаст короткую ссылку. Дальнейший partner-retry уже вернётsuccess: trueсshort_url. Если кейс срочный — напишите в вашу группу с командой заботы EasyPay сidempotency_key.
Идемпотентность и повторы
Сервис рассчитан на безопасные повторы.
Тот же
**idempotency_key**+ то же тело запроса. Возвращается та же ссылка, что и в первый раз. В ответеis_replay: true. Никаких дублей в Stripe. Лимит на 24 часа — после этого та же комбинация ключ+тело создаст новую ссылку.Тот же
**idempotency_key**+ другое тело. Возвращаетсяidempotency_conflict. Никаких изменений на стороне Stripe. Сгенерируйте новый ключ для нового запроса.Тот же
**idempotency_key**+ другая эффективная валюта. Такжеidempotency_conflict. EasyPay сравнивает валюту current request (после override-fallback) с валютой сохранённой ссылки. Если они отличаются — конфликт, даже если остальное тело то же. Для смены валюты сгенерируйте новый ключ.Сетевой сбой посреди обработки (вы не получили ответ). Повторите с тем же ключом и телом — EasyPay подхватит работу с того места, где она прервалась, и вернёт ту же ссылку.
Лимит ретраев. На один
idempotency_keyдопустимо 5 неудачных попыток. После шестого ретрая, который попадает на ту же ошибку, ключ блокируется какfailed_terminal— следующие запросы с ним вернут закэшированную ошибку. Чтобы повторить — сгенерируйте новыйidempotency_key.Зарезервированный префикс.
idempotency_keyне должен начинаться сingest:— этот префикс EasyPay использует внутри себя для записи продуктов, проходящих модерацию через мини-апп. Запрос с таким ключом отклоняется какinvalid_input.
Ограничения
Endpoint доступен только для уже одобренных продуктов. Чтобы создать первую ссылку для нового продукта, используйте мини-апп — чтобы он прошёл модерацию.
Сохраните
short_urlна своей стороне сразу после получения ответа — это рабочая ссылка для дальнейшего использования.success_urlмаксимум 2048 символов.idempotency_keyмаксимум 128 символов и не должен начинаться сingest:.price.currency(если передан) —"USD","EUR","GBP"или"BRL".
Пример на Python
import urllib.request
import json
import uuid
url = "https://n8n.thenextgen.store/webhook/payment-link-create"
payload = {
"auth_mode": "api_key",
"api_key": "ваш-api-ключ",
"stripe_product_id": "prod_XXXXXXXXXXXX",
"price": {
"unit_amount": 9900,
"currency": "EUR" # optional — по умолчанию наследуется от продукта
},
"payment_link": {
"payment_method_types": ["card", "link"],
"allow_promotion_codes": False,
"success_url": "https://example.com/thanks",
"quantity": 1
},
"idempotency_key": str(uuid.uuid4())
}
req = urllib.request.Request(
url,
data=json.dumps(payload).encode("utf-8"),
headers={"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"Short link to share with customer: {result['short_url']}")
print(f"Currency: {result['currency']} ({result['currency_source']})")
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/payment-link-create \
-H "Content-Type: application/json" \
-d '{
"auth_mode": "api_key",
"api_key": "ваш-api-ключ",
"stripe_product_id": "prod_XXXXXXXXXXXX",
"price": { "unit_amount": 9900, "currency": "EUR" },
"payment_link": {
"payment_method_types": ["card", "link"],
"success_url": "https://example.com/thanks"
},
"idempotency_key": "your-unique-key-here"
}'Подписки: пример с триалом
Для продукта-подписки добавьте interval_count и trial_days. Интервал (month / year / …) наследуется от продукта.
{
"auth_mode": "api_key",
"api_key": "ваш-api-ключ",
"stripe_product_id": "prod_SUBSCRIPTION_PRODUCT_ID",
"price": {
"unit_amount": 4900,
"interval_count": 1,
"trial_days": 14
},
"payment_link": {
"allow_promotion_codes": true
},
"idempotency_key": "subscription-link-2026-04-29"
}Если что-то пошло не так
Получили
**unauthorized**— обновите ключ через мини-апп («Show again» на первом шаге онбординга или получить у вашего менеджера).**product_not_found**для продукта, который вы видите в мини-апп — проверьте, что копируете именноstripe_product_id(форматprod_…), а не внутренний номер из Internal Tariffs.**idempotency_conflict**— сгенерируйте новый ключ. Не пытайтесь «починить» существующий: каждое тело запроса (включая валюту) должно иметь свой ключ.**short_url_unavailable**— Stripe Payment Link создан, но short.io в момент запроса не ответил. Напишите в вашу EasyPay-группу с командой заботы сidempotency_key— короткая ссылка будет добавлена вручную, и ваш повторный запрос с тем же ключом вернётsuccess: true.**invalid_input**с сообщением про reserved prefix —idempotency_keyне должен начинаться сingest:. Сгенерируйте новый ключ (например, черезuuid.uuid4()).**invalid_input**с сообщением про currency —price.currencyдолжен быть"USD","EUR","GBP"или"BRL"(case-insensitive). Если хотите унаследовать валюту от продукта — просто не передавайте это поле.Любая другая ситуация — напишите в вашу EasyPay-группу с командой заботы или попросите MCP-агента передать запрос команде заботы.