Перейти к основному содержимому

Вебхуки

Вместо постоянных опросов Glitchmug сам отправит POST на ваш сервер, когда что-то произойдёт с вашими модами или жалобами.

Настройка​

В Настройках → Вебхуки на сайте или ключом со scope webhooks:manage:

ЗапросЧто делает
POST /me/webhooksДобавить: { "url": "https://…", "events": ["version.published"] }. В ответе — секрет подписи secret, показывается один раз
GET /me/webhooksСписок ваших вебхуков с последней отправкой каждого
PATCH /me/webhooks/{id}Изменить url, events или isActive
POST /me/webhooks/{id}/rotateНовый секрет; старый перестаёт работать сразу
POST /me/webhooks/{id}/pingОтправить событие ping прямо сейчас
GET /me/webhooks/{id}/deliveriesПоследние 50 попыток (хранятся 14 дней)
DELETE /me/webhooks/{id}Удалить

До 10 вебхуков на аккаунт. Адрес должен быть https:// и вести в публичный интернет: приватные, loopback и link-local адреса запрещены, в том числе когда публичное имя указывает на такой адрес. Редиректы не выполняются.

События​

СобытиеКогдаdata
mod.updatedЧто-то изменилось в вашем моде: правка, статус, модерацияmod
version.publishedВерсия вашего мода стала публичнойmod, version
comment.createdКто-то прокомментировал ваш модmod, comment
report.resolvedВаша жалоба закрыта (решена или отклонена)report
review.createdКто-то оставил отзыв на ваш модmod, review (id, recommend, body, author, createdAt)
pingВы запросили проверкуwebhook

mod.updated склеивается: несколько изменений за пару секунд приходят одним событием с последним состоянием.

Отправка​

POST /your/endpoint
Content-Type: application/json
User-Agent: glitchmug-webhooks/1
Glitchmug-Event: version.published
Glitchmug-Delivery: 8c1f4a2e-6b7d-4f0e-9a51-2d3c4b5a6e7f
Glitchmug-Signature: t=1792843200,v1=5f2b…

{
"id": "8c1f4a2e-6b7d-4f0e-9a51-2d3c4b5a6e7f",
"event": "version.published",
"createdAt": "2026-10-26T12:00:00.000Z",
"data": {
"mod": {
"id": 1042,
"slug": "neon-haze-skin",
"title": "Neon Haze skin",
"status": "published",
"game": "deadlock",
"url": "https://glitchmug.com/mods/1042/neon-haze-skin",
"updatedAt": "2026-10-26T11:59:58.000Z"
},
"version": { "id": "v1v2v3v4v5v6", "version": "1.2.0", "publishedAt": "2026-10-26T11:59:58.000Z" }
}
}

Ответьте любым 2xx в течение 10 секунд. Тяжёлую работу делайте потом: положите событие в очередь и сразу ответьте.

Проверка подписи​

Glitchmug-Signature имеет вид t=<unix-секунды>,v1=<hex>, где v1 = HMAC-SHA256(secret, "<t>.<сырое тело>").

  1. Возьмите сырые байты тела запроса, до разбора JSON.
  2. Отклоните запрос, если t отличается от текущего времени больше чем на 5 минут (защита от повторов).
  3. Посчитайте HMAC и сравните с v1 за постоянное время.
import { createHmac, timingSafeEqual } from 'node:crypto';

/** Check `Glitchmug-Signature` against the raw request body (not re-serialized JSON). */
export function verify(secret: string, rawBody: string, header: string, now = Date.now()): boolean {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=', 2)));
const t = Number(parts.t);
if (!t || !parts.v1 || Math.abs(now / 1000 - t) > 300) return false; // 5 min replay window
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
const given = Buffer.from(parts.v1, 'hex');
return given.length === expected.length && timingSafeEqual(given, expected);
}

// Self-check with a sample delivery
const secret = 'whsec_example';
const body = '{"id":"6f1c…","event":"ping","createdAt":"2026-10-26T12:00:00.000Z","data":{}}';
const t = Math.floor(Date.now() / 1000);
const v1 = createHmac('sha256', secret).update(`${t}.${body}`).digest('hex');
if (!verify(secret, body, `t=${t},v1=${v1}`)) throw new Error('valid signature rejected');
if (verify(secret, body + ' ', `t=${t},v1=${v1}`)) throw new Error('tampered body accepted');
console.log('signature check ok');

Повторы и отключение​

  • Ответ не 2xx, таймаут или ошибка соединения — 6 повторов: через 1 минуту, 5 минут, 30 минут, 2 часа, 6 часов и 12 часов — около 21 часа от первой попытки до последней. Короткий простой вашего сервера ничего не теряет.
  • У всех попыток одного события одинаковые Glitchmug-Delivery и тело — используйте его, чтобы отбрасывать дубли.
  • После 10 событий подряд, которые не доставились ни с одной попытки, вебхук выключается (isActive: false). Включите его снова через PATCH { "isActive": true } — счётчик ошибок обнулится.
  • Порядок доставки не гарантирован. Если он важен, ориентируйтесь на updatedAt / createdAt в теле.