Endpoint (API v2): Ротация секрета подписи вебхуков
ℹ️ EasyPay API v2. Это ручка второго поколения EasyPay API (база
https://api.appsign.me), пришедшего на смену legacy-API v1 (https://n8n.thenextgen.store/webhook/*). Отличия v2 от v1: авторизация заголовкомX-Partner-Api-Key, плоское тело запроса, идемпотентность черезclient_token(полный ключ собирает сервер), коды ошибок — вUPPER_CASE.
Зачем это нужно
EasyPay подписывает каждый исходящий вебхук HMAC-секретом (см. гайд по проверке подписи). Секрет вы получаете при регистрации вебхука.
Эта ручка меняет секрет для одной среды: генерит новый и оставляет прежний действительным на короткий grace-период. Нужна когда:
есть подозрение на утечку секрета;
вы делаете плановую ротацию по расписанию безопасности.
💡 Просто потеряли секрет? Ротация не нужна. Ручка регистрации — get-or-create: повторный вызов возвращает текущий секрет. Ротация нужна именно чтобы сменить секрет, а не прочитать его.
Grace-период — переход без потери событий
Ротация мгновенно генерирует новый секрет (current) и сохраняет прежний как previous до момента previous_valid_until (по умолчанию 7 дней). Пока идёт grace-период, EasyPay подписывает каждый вебхук обоими секретами — в заголовке EasyPay-Signature появляются два значения через пробел: v1,<hex> v1,<hex>. Вы успеваете раскатить новый секрет по всем инстансам, не теряя ни одного события.
Как подключиться
У вас уже должен быть зарегистрирован вебхук для нужной среды.
Тот же API-ключ и то же разрешение
webhook_config, что и для регистрации.
Endpoint
POST https://api.appsign.me/rotate-partner-webhook-secret
Content-Type: application/json
X-Partner-Api-Key: ваш-api-ключФормат запроса
{
"environment": "live",
"client_token": "rotate-2026-07-10-leak"
}Параметры:
Параметр | Обязательный | Описание |
|---|---|---|
| Да | Среда, для которой ротировать секрет: |
| Да | Идемпотентный токен ротации (см. ниже). |
Идемпотентность
Ротация требует client_token — в отличие от ручек создания, где он опционален. Причина: ротация не идемпотентна по содержимому (каждый вызов обязан выдать новый секрет), поэтому безопасного «дедупа по содержимому» здесь нет.
Каждый уникальный
client_token= одна ротация.Повтор того же
client_tokenне ротирует повторно и возвращает текущий секрет (rotated: false,secret_status: "returned") — безопасный retry.Чтобы ротировать ещё раз, передайте новый
client_token.
Формат ответа
Успешный ответ (200)
{
"success": true,
"environment": "live",
"rotated": true,
"secret_status": "issued",
"signing_secret": "whsec_live_044a6b63…",
"previous_valid_until": "2026-07-17T12:00:00.000Z"
}Поле | Описание |
|---|---|
| Новый секрет ( |
|
|
| ISO8601 — до этого момента прежний секрет ещё проверяет подпись (grace-период). |
|
|
| Среда, для которой ротировали. |
Ошибки
Все ошибки возвращаются с HTTP 200 + полем success: false и error_code. Проверяйте success, а не HTTP-статус.
| Когда срабатывает |
|---|---|
|
|
| Не передан или невалиден API-ключ. |
| У ключа нет разрешения |
| Тот же |
| Прошлая попытка с этим токеном упала. Новый токен. |
| Другой запрос с тем же токеном ещё обрабатывается. Повторите чуть позже. |
| Внутренний сбой EasyPay. Команда заботы уведомлена. |
Как перейти на новый секрет
Вызовите ротацию, получите
signing_secretи разверните его рядом со старым секретом.Принимайте вебхук, если проходит любой из ваших секретов — готовые сниппеты в гайде уже перебирают все значения
v1,в заголовке.Уберите старый секрет до
previous_valid_until.
Ограничения
Ротация — по одной среде за вызов (
testилиliveотдельно).Нужен уже зарегистрированный вебхук и разрешение
webhook_config.client_tokenобязателен (в отличие от ручек создания).Grace-период (действие старого секрета) — по умолчанию 7 дней.
Пример на Python
import urllib.request
import json
import uuid
url = "https://api.appsign.me/rotate-partner-webhook-secret"
payload = {
"environment": "live",
"client_token": f"rotate-{uuid.uuid4().hex[:12]}",
}
req = urllib.request.Request(
url,
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json", "X-Partner-Api-Key": "ваш-api-ключ"},
method="POST",
)
with urllib.request.urlopen(req) as resp:
result = json.loads(resp.read().decode("utf-8"))
if result.get("success") and result.get("secret_status") == "issued":
print("НОВЫЙ секрет (сохраните немедленно!):", result["signing_secret"])
print("Старый секрет действует до:", result.get("previous_valid_until"))
else:
print("Ответ:", result.get("error_code") or result.get("secret_status"))Пример на cURL
curl -X POST "https://api.appsign.me/rotate-partner-webhook-secret" \
-H "Content-Type: application/json" \
-H "X-Partner-Api-Key: ваш-api-ключ" \
-d '{
"environment": "live",
"client_token": "rotate-2026-07-10-leak"
}'См. также
Endpoint (API v2): Регистрация вебхука уведомлений — как зарегистрировать вебхук и получить/восстановить секрет.
Webhook EasyPay: проверка подписи — как проверить подпись вебхука.