Меню

Reference

Webhooks

Recca шлёт события в реальном времени на ваш URL. HMAC-SHA256 подпись в заголовке X-Recca-Signature.

Включение

В /org/<slug>/integration → Webhook укажите URL вашего receiver-а (HTTPS обязательно) и выберите события. Webhook secret выдаётся один раз — храните в vault.

HMAC верификация

Recca подписывает запрос:

X-Recca-Signature: <hex(HMAC-SHA256(webhook_secret, raw_body))>

Express пример (см. также Quickstart Express):

app.post(
  "/api/recca/webhook",
  express.raw({ type: "application/json" }),  // ВАЖНО: raw body
  (req, res) => {
    const sig = req.header("X-Recca-Signature") || ""
    const expected = crypto
      .createHmac("sha256", process.env.RECCA_WEBHOOK_SECRET!)
      .update(req.body as Buffer)
      .digest("hex")
    if (sig !== expected) return res.status(401).end()

    const event = JSON.parse(req.body.toString("utf-8"))
    // dispatch on event.event_type
    res.json({ received: true })
  }
)

Каталог событий

lead.created

Новый лид зарегистрирован через POST /federation/v1/leads ИЛИ через виджет lead-form ИЛИ через embed referral-link редирект.

{
  "event_type": "lead.created",
  "event_id": "evt_01HXVB...",
  "occurred_at": "2026-05-16T10:00:00Z",
  "payload": {
    "lead_id": "lead_01HXVB...",
    "referrer_user_id": "usr_01HXVB...",
    "contact": { "name": "Анна", "email": "a@example.ru" },
    "offer_id": null,
    "metadata": {}
  }
}

bonus.pending

Бонус начислен в pending (например, после lead.created с настроенным авто-бонусом) — ещё не доступен партнёру.

{
  "event_type": "bonus.pending",
  "payload": {
    "bonus_id": "bns_01HXVB...",
    "user_id": "usr_01HXVB...",
    "amount_kopecks": 250000,
    "currency": "RUB",
    "source_type": "lead", "source_id": "lead_01..."
  }
}

bonus.approved

Pending-бонус подтверждён (вручную в админке или автоматически после grace-периода).

{
  "event_type": "bonus.approved",
  "payload": { "bonus_id", "user_id", "amount_kopecks", "approved_at" }
}

bonus.rejected

Pending-бонус отклонён в админке.

{
  "event_type": "bonus.rejected",
  "payload": { "bonus_id", "user_id", "amount_kopecks", "rejected_at", "reason" }
}

conversion.cascaded

POST /federation/v1/conversions/register успешно — бонусы распределены по сети (referrer + uplines).

{
  "event_type": "conversion.cascaded",
  "payload": {
    "conversion_id": "cnv_01HXVB...",
    "lead_id": "lead_01HXVB...",
    "amount_kopecks": 1280000,
    "cascaded_bonuses": [
      { "user_id": "usr_01...", "amount_kopecks": 250000, "tier": "referrer" },
      { "user_id": "usr_02...", "amount_kopecks": 50000,  "tier": "upline_1" }
    ]
  }
}

conversion.reversed

Конверсия отменена (return / refund) — каскадные бонусы списываются.

{
  "event_type": "conversion.reversed",
  "payload": { "conversion_id", "reversed_at", "reason" }
}

Повторы и идемпотентность

При неуспешной доставке (non-2xx response или timeout) Recca повторяет с экспоненциальным backoff: 30 сек → 5 мин → 30 мин → 4 часа → 24 часа. После 5 неуспешных попыток событие попадает в DLQ; владелец получает уведомление в /org/<slug>/audit-log.

event_id уникален per событие — храните обработанные ID на своей стороне, чтобы при повторной доставке не дублировать работу.