Create a webhook endpoint
const url = 'https://api.keliplay.com/v1/tenant/webhooks/endpoints';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"url":"https://hooks.example.com/keliplay","events":["session_completed","winner_selected","reward_granted"],"channelIds":["0192f3a1-0000-7000-8000-00000000c001"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.keliplay.com/v1/tenant/webhooks/endpoints \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "url": "https://hooks.example.com/keliplay", "events": [ "session_completed", "winner_selected", "reward_granted" ], "channelIds": [ "0192f3a1-0000-7000-8000-00000000c001" ] }'Registers an https URL to receive events. The response includes
secret, which you use to check the X-Keliplay-Signature header on each
delivery. Store it.
Leave gameInstanceIds and channelIds empty to receive events from
every campaign. Fill either to receive only events from those campaigns,
or from campaigns on those channels.
The URL must be public https.
Set includeCouponCodes to true to receive the coupon code in
reward_granted events, as coupon.code. This also needs the
rewards.codes.manage permission (403 without it). Anyone who can read
requests to the URL can read the codes. Codes never appear in the
delivery log.
Permission: webhooks.manage. Plan feature: Webhooks. Plan limit:
number of endpoints.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
Only events from these campaigns.
Only events from campaigns on these channels.
Send the coupon code in reward_granted. true also needs
rewards.codes.manage.
Example
{ "url": "https://hooks.example.com/keliplay", "events": [ "session_completed", "winner_selected", "reward_granted" ], "channelIds": [ "0192f3a1-0000-7000-8000-00000000c001" ]}Responses
Section titled “Responses”The new endpoint, with its signing secret.
object
object
Only events from these campaigns. Empty with empty channelIds means every campaign.
Only events from campaigns on these channels.
Whether reward_granted events to this endpoint carry the coupon code.
Present on responses that create or change an endpoint.
The signing secret for X-Keliplay-Signature. Shown only when the endpoint is created. Keep it private.
Example
{ "endpoint": { "id": "0192f3a1-0000-7000-8000-0000000b0001", "url": "https://hooks.example.com/keliplay", "secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "events": [ "session_completed", "winner_selected", "reward_granted" ], "gameInstanceIds": [], "channelIds": [ "0192f3a1-0000-7000-8000-00000000c001" ], "status": "active", "createdAt": "2026-09-01T09:00:00.000Z", "updatedAt": "2026-09-01T09:00:00.000Z" }}The request is not valid. details lists each field that failed, where there is one.
object
object
Stable and safe to branch on.
invalid_request(400): the request is not valid.unauthorized(401): missing, malformed or revoked API key.upgrade_required(402): not in your plan, or a plan limit is reached.forbidden(403): the key lacks a permission, or the action is not allowed.not_found(404): nothing with that id in your account.conflict(409): clashes with the current state.confirmation_required(409): repeat withconfirm=true. Folder deletion only.rate_limited(429): wait forRetry-Afterseconds.internal_error(500) andservice_unavailable(503): try again later.
Written for a person. May change; do not parse it.
object
The failing field, dot separated, such as prize.label.
object
Example
{ "error": { "code": "invalid_request", "message": "Invalid request json.", "details": [ { "path": "name", "message": "Too small, expected string to have >=1 characters" } ] }}The API key is missing, malformed or revoked.
object
object
Stable and safe to branch on.
invalid_request(400): the request is not valid.unauthorized(401): missing, malformed or revoked API key.upgrade_required(402): not in your plan, or a plan limit is reached.forbidden(403): the key lacks a permission, or the action is not allowed.not_found(404): nothing with that id in your account.conflict(409): clashes with the current state.confirmation_required(409): repeat withconfirm=true. Folder deletion only.rate_limited(429): wait forRetry-Afterseconds.internal_error(500) andservice_unavailable(503): try again later.
Written for a person. May change; do not parse it.
object
The failing field, dot separated, such as prize.label.
object
Example
{ "error": { "code": "unauthorized", "message": "Invalid or revoked API key." }}Your plan does not include this feature, or you have reached a plan limit.
object
object
Stable and safe to branch on.
invalid_request(400): the request is not valid.unauthorized(401): missing, malformed or revoked API key.upgrade_required(402): not in your plan, or a plan limit is reached.forbidden(403): the key lacks a permission, or the action is not allowed.not_found(404): nothing with that id in your account.conflict(409): clashes with the current state.confirmation_required(409): repeat withconfirm=true. Folder deletion only.rate_limited(429): wait forRetry-Afterseconds.internal_error(500) andservice_unavailable(503): try again later.
Written for a person. May change; do not parse it.
object
The failing field, dot separated, such as prize.label.
object
Example
{ "error": { "code": "upgrade_required", "message": "Rewards is not included in your plan. Ask whoever manages your account to add it." }}The API key does not carry the permission this needs, or the request is not allowed.
object
object
Stable and safe to branch on.
invalid_request(400): the request is not valid.unauthorized(401): missing, malformed or revoked API key.upgrade_required(402): not in your plan, or a plan limit is reached.forbidden(403): the key lacks a permission, or the action is not allowed.not_found(404): nothing with that id in your account.conflict(409): clashes with the current state.confirmation_required(409): repeat withconfirm=true. Folder deletion only.rate_limited(429): wait forRetry-Afterseconds.internal_error(500) andservice_unavailable(503): try again later.
Written for a person. May change; do not parse it.
object
The failing field, dot separated, such as prize.label.
object
Example
{ "error": { "code": "forbidden", "message": "Your role does not allow this (draws.run)." }}