Skip to content

Create a webhook endpoint

POST
/v1/tenant/webhooks/endpoints
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.

Media typeapplication/json
object
url
required
string format: uri
<= 2048 characters
events
required
Array<string>
>= 1 items
Allowed values: session_completed winner_selected reward_granted
gameInstanceIds

Only events from these campaigns.

Array<string>
default: <= 200 items
channelIds

Only events from campaigns on these channels.

Array<string>
default: <= 200 items
includeCouponCodes

Send the coupon code in reward_granted. true also needs rewards.codes.manage.

boolean
Example
{
"url": "https://hooks.example.com/keliplay",
"events": [
"session_completed",
"winner_selected",
"reward_granted"
],
"channelIds": [
"0192f3a1-0000-7000-8000-00000000c001"
]
}

The new endpoint, with its signing secret.

Media typeapplication/json
object
endpoint
required
object
id
required
string
url
required
string format: uri
events
required
Array<string>
Allowed values: session_completed winner_selected reward_granted
gameInstanceIds
required

Only events from these campaigns. Empty with empty channelIds means every campaign.

Array<string>
channelIds
required

Only events from campaigns on these channels.

Array<string>
includeCouponCodes

Whether reward_granted events to this endpoint carry the coupon code.

boolean
status
required
string
Allowed values: active disabled
createdAt
required
string format: date-time
updatedAt

Present on responses that create or change an endpoint.

string format: date-time
secret
required

The signing secret for X-Keliplay-Signature. Shown only when the endpoint is created. Keep it private.

string
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.

Media typeapplication/json
object
error
required
object
code
required

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 with confirm=true. Folder deletion only.
  • rate_limited (429): wait for Retry-After seconds.
  • internal_error (500) and service_unavailable (503): try again later.
string
Allowed values: invalid_request unauthorized upgrade_required forbidden not_found conflict confirmation_required rate_limited internal_error service_unavailable
message
required

Written for a person. May change; do not parse it.

string
details
One of:
Array<object>
object
path
required

The failing field, dot separated, such as prize.label.

string
message
required
string
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.

Media typeapplication/json
object
error
required
object
code
required

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 with confirm=true. Folder deletion only.
  • rate_limited (429): wait for Retry-After seconds.
  • internal_error (500) and service_unavailable (503): try again later.
string
Allowed values: invalid_request unauthorized upgrade_required forbidden not_found conflict confirmation_required rate_limited internal_error service_unavailable
message
required

Written for a person. May change; do not parse it.

string
details
One of:
Array<object>
object
path
required

The failing field, dot separated, such as prize.label.

string
message
required
string
Example
{
"error": {
"code": "unauthorized",
"message": "Invalid or revoked API key."
}
}

Your plan does not include this feature, or you have reached a plan limit.

Media typeapplication/json
object
error
required
object
code
required

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 with confirm=true. Folder deletion only.
  • rate_limited (429): wait for Retry-After seconds.
  • internal_error (500) and service_unavailable (503): try again later.
string
Allowed values: invalid_request unauthorized upgrade_required forbidden not_found conflict confirmation_required rate_limited internal_error service_unavailable
message
required

Written for a person. May change; do not parse it.

string
details
One of:
Array<object>
object
path
required

The failing field, dot separated, such as prize.label.

string
message
required
string
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.

Media typeapplication/json
object
error
required
object
code
required

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 with confirm=true. Folder deletion only.
  • rate_limited (429): wait for Retry-After seconds.
  • internal_error (500) and service_unavailable (503): try again later.
string
Allowed values: invalid_request unauthorized upgrade_required forbidden not_found conflict confirmation_required rate_limited internal_error service_unavailable
message
required

Written for a person. May change; do not parse it.

string
details
One of:
Array<object>
object
path
required

The failing field, dot separated, such as prize.label.

string
message
required
string
Example
{
"error": {
"code": "forbidden",
"message": "Your role does not allow this (draws.run)."
}
}