Перейти к содержимому
KinetX
Operator API v1

Вебхуки

Получайте уведомления в момент любого события на платформе — регистрации, платежи, бонусы, решения KYC и сигналы комплаенса — подписанными HTTPS-запросами на ваши серверы.

Обзор

Сотрудники добавляют адреса вебхуков в бэк-офисе (Инструменты → API и вебхуки → Вебхуки): HTTPS-адрес, события, на которые он подписан, и секрет подписи, показываемый один раз. Кнопка «Отправить тестовое событие» отправляет ping, а журнал доставок показывает каждую попытку с ответом и позволяет повторить её.

События возникают для всего, что происходит в вашем аккаунте оператора, — через API, ваш сайт на KinetX, бэк-офис или плановую задачу.

Каждая доставка — POST с телом JSON и следующими заголовками:

X-KinetX-EventТип события, например deposit.paid.
X-KinetX-Event-IdУникальный id события (есть и в теле); используйте его, чтобы обработать каждое событие один раз.
X-KinetX-DeliveryId доставки, одинаковый для всех повторов этой доставки.
X-KinetX-TimestampUnix-время этой попытки, часть подписи.
X-KinetX-SignatureHex HMAC-SHA256 от «{timestamp}.{сырое тело}» с ключом — секретом адреса.

События

Тело всегда имеет одну обёртку — id, type, api_version, created_at и data события. Объекты data — те же ресурсы, что возвращает API.

player.registered Игрок зарегистрировался (сайт, бэк-офис или API)
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "player.registered",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe",
            "email": "jane@example.com",
            "first_name": "Jane",
            "middle_name": null,
            "last_name": "Doe",
            "gender": "female",
            "birth_date": "1990-04-12",
            "country": "MT",
            "city": "Valletta",
            "address": "12 Republic Street",
            "zip_code": "VLT 1110",
            "phone": "+35699123456",
            "personal_id": null,
            "document_number": "P1234567",
            "language": "en",
            "currency": "EUR",
            "status": "active",
            "category": "new_user",
            "kyc_status": "not_started",
            "is_verified": false,
            "risk_level": "low",
            "is_test": false,
            "restrictions": {
                "can_login": true,
                "can_deposit": true,
                "can_withdraw": true,
                "can_bet": true,
                "excluded_from_bonuses": false
            },
            "self_exclusion": null,
            "marketing": {
                "email": true,
                "sms": false,
                "newsletter": false
            },
            "registration": {
                "source": "api",
                "ip": "203.0.113.10",
                "promo_code": "WELCOME100",
                "affiliate_id": "aff-204",
                "btag": null
            },
            "last_login_at": null,
            "created_at": "2026-10-15T09:30:00Z",
            "updated_at": "2026-10-15T09:30:00Z"
        }
    }
}
deposit.paid Депозит оплачен и зачислен на кошелёк
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "deposit.paid",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "payment": {
            "id": 5120,
            "type": "deposit",
            "status": "paid",
            "player_id": 1042,
            "amount": 10000,
            "currency": "EUR",
            "payment_method": "visa-mastercard",
            "external_reference": "psp_tx_7781",
            "info": null,
            "reject_reason": null,
            "is_reversed": false,
            "created_at": "2026-10-15T09:30:00Z",
            "paid_at": "2026-10-15T09:30:00Z",
            "rejected_at": null,
            "cancelled_at": null,
            "updated_at": "2026-10-15T09:30:00Z"
        },
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe"
        }
    }
}
withdrawal.requested Игрок запросил вывод (сумма зарезервирована)
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "withdrawal.requested",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "payment": {
            "id": 5121,
            "type": "withdrawal",
            "status": "new",
            "player_id": 1042,
            "amount": 5000,
            "currency": "EUR",
            "payment_method": "visa-mastercard",
            "external_reference": "wd_20261015_001",
            "info": "Visa **** 4242",
            "reject_reason": null,
            "is_reversed": false,
            "created_at": "2026-10-15T09:30:00Z",
            "paid_at": null,
            "rejected_at": null,
            "cancelled_at": null,
            "updated_at": "2026-10-15T09:30:00Z"
        },
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe"
        }
    }
}
withdrawal.paid Вывод выплачен
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "withdrawal.paid",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "payment": {
            "id": 5121,
            "type": "withdrawal",
            "status": "paid",
            "player_id": 1042,
            "amount": 5000,
            "currency": "EUR",
            "payment_method": "visa-mastercard",
            "external_reference": "wd_20261015_001",
            "info": "Visa **** 4242",
            "reject_reason": null,
            "is_reversed": false,
            "created_at": "2026-10-15T09:30:00Z",
            "paid_at": "2026-10-15T09:30:00Z",
            "rejected_at": null,
            "cancelled_at": null,
            "updated_at": "2026-10-15T09:30:00Z"
        },
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe"
        }
    }
}
withdrawal.rejected Вывод отклонён, сумма возвращена
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "withdrawal.rejected",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "payment": {
            "id": 5121,
            "type": "withdrawal",
            "status": "rejected",
            "player_id": 1042,
            "amount": 5000,
            "currency": "EUR",
            "payment_method": "visa-mastercard",
            "external_reference": "wd_20261015_001",
            "info": "Visa **** 4242",
            "reject_reason": "Proof of address required",
            "is_reversed": false,
            "created_at": "2026-10-15T09:30:00Z",
            "paid_at": null,
            "rejected_at": "2026-10-15T09:30:00Z",
            "cancelled_at": null,
            "updated_at": "2026-10-15T09:30:00Z"
        },
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe"
        }
    }
}
bonus.granted Игроку начислен бонус
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "bonus.granted",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "bonus": {
            "id": 9001,
            "player_id": 1042,
            "bonus_id": 12,
            "name": "Welcome Bonus 100%",
            "type": "wagering_bonus",
            "state": "activated",
            "result": "none",
            "amount": 20000,
            "currency": "EUR",
            "wager_requirement": 700000,
            "wagered_amount": 175000,
            "wagering_progress": 25,
            "converted_amount": 0,
            "forfeited_amount": 0,
            "max_bet": 500,
            "started_at": "2026-10-15T09:30:00Z",
            "expires_at": "2026-11-14T09:30:00Z",
            "finished_at": null,
            "created_at": "2026-10-15T09:30:00Z"
        },
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe"
        }
    }
}
bonus.completed Бонус завершён (конвертирован, проигран, истёк или отменён)
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "bonus.completed",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "bonus": {
            "id": 9001,
            "player_id": 1042,
            "bonus_id": 12,
            "name": "Welcome Bonus 100%",
            "type": "wagering_bonus",
            "state": "finished",
            "result": "paid",
            "amount": 20000,
            "currency": "EUR",
            "wager_requirement": 700000,
            "wagered_amount": 700000,
            "wagering_progress": 100,
            "converted_amount": 18250,
            "forfeited_amount": 0,
            "max_bet": 500,
            "started_at": "2026-10-15T09:30:00Z",
            "expires_at": "2026-11-14T09:30:00Z",
            "finished_at": "2026-10-20T18:02:11Z",
            "created_at": "2026-10-15T09:30:00Z"
        },
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe"
        }
    }
}
kyc.status_changed Изменился статус KYC игрока
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "kyc.status_changed",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe"
        },
        "previous_status": "pending_review",
        "status": "verified",
        "is_verified": true
    }
}
compliance.alert_created Риск-движок создал сигнал комплаенса (AML)
json
{
    "id": "evt_01jaq3w8z6x4t2v9r7p5n3m1k0",
    "type": "compliance.alert_created",
    "api_version": "v1",
    "created_at": "2026-10-15T09:30:00Z",
    "data": {
        "alert": {
            "id": 77,
            "rule": "large_deposit",
            "severity": "high",
            "status": "open",
            "created_at": "2026-10-15T09:30:00Z"
        },
        "player": {
            "id": 1042,
            "external_id": "op-58213",
            "username": "jane_doe"
        }
    }
}

Доставка и повторы

  • Доставки отправляются сразу после фиксации изменения. Ответьте любым статусом 2xx в течение 5 секунд; перенаправления не выполняются.
  • Любой другой ответ, тайм-аут или ошибка соединения повторяются с экспоненциальной задержкой — через 1, 2, 4, 8, 16, 32 и 64 минуты — всего до 8 попыток, после чего доставка помечается неудачной. Сотрудники могут повторить любую доставку из журнала.
  • События изменений, которые были откатены, никогда не отправляются.
  • Доставки могут приходить повторно и не по порядку. Устраняйте дубли по id события и упорядочивайте по created_at или состоянию ресурса.

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

Вычисляйте HMAC от сырого тела запроса ровно в полученном виде, сравнивайте за постоянное время и отклоняйте метки времени старше пяти минут:

<?php

$secret = getenv('KINETX_WEBHOOK_SECRET');   // whsec_…
$body = file_get_contents('php://input');      // the raw body, before any JSON parsing
$timestamp = $_SERVER['HTTP_X_KINETX_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_KINETX_SIGNATURE'] ?? '';

$expected = hash_hmac('sha256', $timestamp.'.'.$body, $secret);

if (! hash_equals($expected, $signature) || abs(time() - (int) $timestamp) > 300) {
    http_response_code(400);
    exit;
}

$event = json_decode($body, true);

// Deliveries can repeat: process each event id once.
if (! already_processed($event['id'])) {
    handle($event['type'], $event['data']);
}

http_response_code(204);

Рекомендации

  • Отвечайте быстро и обрабатывайте асинхронно (поставьте событие в очередь, ответьте 204).
  • Считайте вебхуки уведомлениями: при сомнении запросите текущее состояние через API (например, GET /api/v1/operator/payments/{payment}).
  • Подписывайте каждый адрес только на нужные ему события и меняйте секрет при подозрении на утечку.