Skip to content

Update a campaign

PATCH
/v1/game-instances/{campaignId}
curl --request PATCH \
--url https://api.keliplay.com/v1/game-instances/example \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "name": "Autumn wheel (week 2)", "prize": { "label": "10% off" }, "liveUntil": "2026-11-07T23:59:59.000Z" }'

Changes any part of a campaign. Send only the fields you want to change. Fields you leave out keep their value. Send null to clear a nullable field.

The permission depends on what you send:

  • config: config.write.
  • channelId, liveFrom, liveUntil: channels.manage.
  • status: active: campaigns.activate. Any other status: campaigns.write.
  • theme.labels: copy.write. Other theme fields: branding.write. theme: null needs both.
  • Everything else (name, prize, winner selection, play limits): campaigns.write.

An archived campaign cannot be edited (409). Restore it first by sending only status with another value. A campaign that has been played cannot move to another channel (409). Setting status to active checks the game config and your plan’s limit on live campaigns, as activation does.

campaignId
required
string

The campaign’s id.

Media typeapplication/json
object
name
string
>= 1 characters <= 200 characters
config

The game’s own settings, such as wheel segments or quiz questions. The shape is different for each game. See the Games section for each game’s fields.

Each file a config names must be the right kind: a file under sounds a sound, any other an image. A file from your media library is checked by its type, any other address by its file extension. A mismatch is a 400 naming the field, such as config.art.background.

object
key
additional properties
any
prize

What the campaign is giving away, as shown to winners.

object
label
required
string
>= 1 characters
description
string
externalRef

Your own reference for the prize, such as a SKU.

string
winnerSelectionTrigger

When winners are drawn.

  • manual: when you call the draw operation.
  • auto_on_session_end: after each play ends.
  • auto_on_schedule: once, at scheduleAt.
string
default: manual
Allowed values: manual auto_on_session_end auto_on_schedule
winnerSelectionAlgorithm

How winners are picked from eligible entries. Defaults to the game’s defaultWinnerAlgorithm.

  • random_uniform: every entry has the same chance.
  • random_weighted: chance follows each entry’s weight.
  • score_highest: highest scores win.
string
Allowed values: random_uniform random_weighted score_highest
winnerSelectionConfig
object
maxWinners
integer
>= 1 <= 1000
tieBreak

How equal scores are ordered, for score_highest.

string
Allowed values: earliest_entry random
windowStart

Only entries made at or after this time count.

string format: date-time
windowEnd

Only entries made before this time count.

string format: date-time
scheduleAt
string format: date-time
status
  • draft: being set up. Players cannot see it.
  • active: live on its channel, during its live window.
  • paused: hidden for now. Plays and results are kept.
  • archived: finished and put away. Can be restored.
string
Allowed values: draft active paused archived
theme
One of:

Colours, images, font, wording, background, position and decorations for your games.

Each file must be the kind its field takes: logoUrl and backgroundUrl an image, an animation or decoration the kind it names. A file from your media library is checked by its type, any other address by its file extension. A mismatch is a 400 naming the field.

object
colors

Six-digit hex colours, such as #3b8ad9.

object
bg
string
/^#[0-9a-fA-F]{6}$/
fg
string
/^#[0-9a-fA-F]{6}$/
muted
string
/^#[0-9a-fA-F]{6}$/
accent
string
/^#[0-9a-fA-F]{6}$/
danger
string
/^#[0-9a-fA-F]{6}$/
surface
string
/^#[0-9a-fA-F]{6}$/
border
string
/^#[0-9a-fA-F]{6}$/
logoUrl

An https URL, or a file from your media library.

string
<= 2048 characters
backgroundUrl

The background image, or an animation’s still. An https URL, or a file from your media library.

string
<= 2048 characters
fontFamily

A CSS font family list. Letters, digits, spaces, quotes, commas and hyphens.

string
>= 1 characters <= 120 characters /^[\w ,'"-]+$/
fontUrl

Where to load the font from.

string
<= 2048 characters
labels

Your own wording for player-facing text, keyed by label. Each game lists its label keys in labelKeys.

object
<= 40 properties
key
additional properties
string
<= 200 characters
layout

Where the game sits when it fills a phone’s screen. Has no effect inside a website’s frame.

object
position

Defaults to center.

string
Allowed values: top center bottom
width

game keeps each game’s own width, wide allows at least 560 pixels, full uses the whole screen.

string
Allowed values: game wide full
background

How the background is painted, on the pre-game page, the game and the reward page.

object
fit

How backgroundUrl fills the screen. Defaults to cover.

string
Allowed values: cover contain tile
focus

The part of the image kept in view when it is cropped. Defaults to center.

string
Allowed values: top-left top top-right left center right bottom-left bottom bottom-right
gradient

Painted in place of the flat colors.bg.

object
from
required
string
/^#[0-9a-fA-F]{6}$/
to
required
string
/^#[0-9a-fA-F]{6}$/
angle
required
integer
<= 359
overlay

A tint over the background, for legibility.

object
color
required
string
/^#[0-9a-fA-F]{6}$/
opacity
required

Percent.

integer
<= 80
animation

Moving art from your media library. backgroundUrl is shown first, and instead when motion is off, data is being saved, or it cannot play. Videos play muted, only when the game fills a phone’s screen.

object
kind
required
string
Allowed values: lottie video
url
required
string
<= 2048 characters
decorations

Artwork along the top and bottom edges. It never covers the game.

object
top
object
url
required

An https URL, or a file from your media library. An image repeats along its edge.

string
<= 2048 characters
kind
required
string
Allowed values: image lottie
size
required

The height of its band, 48, 96 or 160 pixels.

string
Allowed values: small medium large
bottom
object
url
required

An https URL, or a file from your media library. An image repeats along its edge.

string
<= 2048 characters
kind
required
string
Allowed values: image lottie
size
required

The height of its band, 48, 96 or 160 pixels.

string
Allowed values: small medium large
maxPlaysPerParticipant

Most plays allowed per player. Null removes the limit. Leave out to keep the current value.

integer | null
>= 1 <= 10000
maxPlaysPerParticipantPerDay

Most plays allowed per player. Null removes the limit. Leave out to keep the current value.

integer | null
>= 1 <= 10000
playLimitTimezone

IANA time zone that decides when a day starts for the daily limit, such as Europe/London.

string
default: UTC >= 1 characters <= 64 characters
channelId

Move the campaign to another of your channels. Only before it has been played.

string
>= 1 characters
liveFrom
string | null format: date-time
liveUntil
string | null format: date-time
Example
{
"name": "Autumn wheel (week 2)",
"prize": {
"label": "10% off"
},
"liveUntil": "2026-11-07T23:59:59.000Z"
}

The updated campaign.

Media typeapplication/json
object
gameInstance
required
object
id
required
string
gameId
required
string
gameSlug
required
string
name
required
string
status
required
  • draft: being set up. Players cannot see it.
  • active: live on its channel, during its live window.
  • paused: hidden for now. Plays and results are kept.
  • archived: finished and put away. Can be restored.
string
Allowed values: draft active paused archived
channelId
required
string
config
required

The game’s own settings, such as wheel segments or quiz questions. The shape is different for each game. See the Games section for each game’s fields.

Each file a config names must be the right kind: a file under sounds a sound, any other an image. A file from your media library is checked by its type, any other address by its file extension. A mismatch is a 400 naming the field, such as config.art.background.

object
key
additional properties
any
prize
One of:

What the campaign is giving away, as shown to winners.

object
label
required
string
>= 1 characters
description
string
externalRef

Your own reference for the prize, such as a SKU.

string
theme
One of:

Colours, images, font, wording, background, position and decorations for your games.

Each file must be the kind its field takes: logoUrl and backgroundUrl an image, an animation or decoration the kind it names. A file from your media library is checked by its type, any other address by its file extension. A mismatch is a 400 naming the field.

object
colors

Six-digit hex colours, such as #3b8ad9.

object
bg
string
/^#[0-9a-fA-F]{6}$/
fg
string
/^#[0-9a-fA-F]{6}$/
muted
string
/^#[0-9a-fA-F]{6}$/
accent
string
/^#[0-9a-fA-F]{6}$/
danger
string
/^#[0-9a-fA-F]{6}$/
surface
string
/^#[0-9a-fA-F]{6}$/
border
string
/^#[0-9a-fA-F]{6}$/
logoUrl

An https URL, or a file from your media library.

string
<= 2048 characters
backgroundUrl

The background image, or an animation’s still. An https URL, or a file from your media library.

string
<= 2048 characters
fontFamily

A CSS font family list. Letters, digits, spaces, quotes, commas and hyphens.

string
>= 1 characters <= 120 characters /^[\w ,'"-]+$/
fontUrl

Where to load the font from.

string
<= 2048 characters
labels

Your own wording for player-facing text, keyed by label. Each game lists its label keys in labelKeys.

object
<= 40 properties
key
additional properties
string
<= 200 characters
layout

Where the game sits when it fills a phone’s screen. Has no effect inside a website’s frame.

object
position

Defaults to center.

string
Allowed values: top center bottom
width

game keeps each game’s own width, wide allows at least 560 pixels, full uses the whole screen.

string
Allowed values: game wide full
background

How the background is painted, on the pre-game page, the game and the reward page.

object
fit

How backgroundUrl fills the screen. Defaults to cover.

string
Allowed values: cover contain tile
focus

The part of the image kept in view when it is cropped. Defaults to center.

string
Allowed values: top-left top top-right left center right bottom-left bottom bottom-right
gradient

Painted in place of the flat colors.bg.

object
from
required
string
/^#[0-9a-fA-F]{6}$/
to
required
string
/^#[0-9a-fA-F]{6}$/
angle
required
integer
<= 359
overlay

A tint over the background, for legibility.

object
color
required
string
/^#[0-9a-fA-F]{6}$/
opacity
required

Percent.

integer
<= 80
animation

Moving art from your media library. backgroundUrl is shown first, and instead when motion is off, data is being saved, or it cannot play. Videos play muted, only when the game fills a phone’s screen.

object
kind
required
string
Allowed values: lottie video
url
required
string
<= 2048 characters
decorations

Artwork along the top and bottom edges. It never covers the game.

object
top
object
url
required

An https URL, or a file from your media library. An image repeats along its edge.

string
<= 2048 characters
kind
required
string
Allowed values: image lottie
size
required

The height of its band, 48, 96 or 160 pixels.

string
Allowed values: small medium large
bottom
object
url
required

An https URL, or a file from your media library. An image repeats along its edge.

string
<= 2048 characters
kind
required
string
Allowed values: image lottie
size
required

The height of its band, 48, 96 or 160 pixels.

string
Allowed values: small medium large
grantOncePerParticipant

Whether a player can receive at most one coupon from this campaign. Set it with the reward.

boolean
rewardValidForSeconds

How long a granted coupon stays valid. Set it with the reward.

integer | null
winnerSelectionTrigger
required

When winners are drawn.

  • manual: when you call the draw operation.
  • auto_on_session_end: after each play ends.
  • auto_on_schedule: once, at scheduleAt.
string
default: manual
Allowed values: manual auto_on_session_end auto_on_schedule
winnerSelectionAlgorithm
required

How winners are picked from eligible entries. Defaults to the game’s defaultWinnerAlgorithm.

  • random_uniform: every entry has the same chance.
  • random_weighted: chance follows each entry’s weight.
  • score_highest: highest scores win.
string
Allowed values: random_uniform random_weighted score_highest
winnerSelectionConfig
required
object
maxWinners
integer
>= 1 <= 1000
tieBreak

How equal scores are ordered, for score_highest.

string
Allowed values: earliest_entry random
windowStart

Only entries made at or after this time count.

string format: date-time
windowEnd

Only entries made before this time count.

string format: date-time
scheduleAt

When an auto_on_schedule draw runs.

string | null format: date-time
resolvedOptionId

The option that happened, on a prediction campaign.

string | null
resolvedAt
string | null format: date-time
maxPlaysPerParticipant
integer | null
maxPlaysPerParticipantPerDay
integer | null
playLimitTimezone
required
string
liveFrom
string | null format: date-time
liveUntil
string | null format: date-time
activatedAt

When the campaign was first activated.

string | null format: date-time
createdAt
required
string format: date-time
updatedAt
required
string format: date-time
Examples
Exampleupdated

A campaign response

{
"gameInstance": {
"id": "0192f3a1-0000-7000-8000-0000000ca001",
"gameId": "0192f3a1-0000-7000-8000-0000000a9001",
"gameSlug": "spin-wheel",
"name": "Autumn wheel",
"status": "active",
"channelId": "0192f3a1-0000-7000-8000-00000000c001",
"config": {
"segments": [
{
"id": "segment-1",
"label": "Free coffee",
"weight": 1
},
{
"id": "segment-2",
"label": "Try again",
"weight": 4
}
]
},
"prize": {
"label": "Free coffee",
"description": "One regular coffee at any store."
},
"theme": null,
"grantOncePerParticipant": true,
"rewardValidForSeconds": 2592000,
"winnerSelectionTrigger": "manual",
"winnerSelectionAlgorithm": "random_weighted",
"winnerSelectionConfig": {
"maxWinners": 3
},
"scheduleAt": null,
"resolvedOptionId": null,
"resolvedAt": null,
"maxPlaysPerParticipant": null,
"maxPlaysPerParticipantPerDay": 1,
"playLimitTimezone": "Europe/London",
"liveFrom": "2026-10-01T00:00:00.000Z",
"liveUntil": "2026-10-31T23:59:59.000Z",
"activatedAt": "2026-09-30T12:00:00.000Z",
"createdAt": "2026-09-25T09:00:00.000Z",
"updatedAt": "2026-09-30T12: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)."
}
}

Nothing with that id exists in your account.

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": "not_found",
"message": "Channel 0192f3a1-0000-7000-8000-00000000c009 not found."
}
}

The request clashes with the current state. The message says what to change.

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": "conflict",
"message": "An archived campaign cannot be edited. Restore it first, then make the change."
}
}