Skip to content

Start an upload

POST
/v1/tenant/assets/presign
curl --request POST \
--url https://api.keliplay.com/v1/tenant/assets/presign \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "filename": "autumn-banner.png", "contentType": "image/png", "sizeBytes": 482113, "folderId": "0192f3a1-0000-7000-8000-0000000f1001" }'

Starts an upload in two steps:

  1. Call this with the file’s name and type. You get an upload url, form fields and a pending asset.
  2. Send the file as a multipart/form-data POST to upload.url, with every entry of upload.fields as a form field and the file last, as file. Then call POST /v1/tenant/assets/{assetId}/confirm.

Size limits: images 8 MB, audio 16 MB, video 50 MB, Lottie animations 2 MB.

Permission: assets.manage. Plan feature: Media library. Plan limit: library storage.

Media typeapplication/json
object
filename
required
string
>= 1 characters <= 200 characters
contentType
required

application/json is for Lottie animations.

string
Allowed values: image/png image/jpeg image/webp image/gif audio/mpeg audio/ogg audio/wav video/mp4 video/webm application/json
sizeBytes

The file’s size, so a file over your storage limit is refused before you upload it.

integer
>= 1 <= 52428800
folderId
string | null
<= 64 characters
Example
{
"filename": "autumn-banner.png",
"contentType": "image/png",
"sizeBytes": 482113,
"folderId": "0192f3a1-0000-7000-8000-0000000f1001"
}

Where to upload, and the pending file record.

Media typeapplication/json
object
upload
required
object
url
required
string format: uri
fields
required
object
key
additional properties
string
asset
required

A file in your media library.

object
id
required
string
url
required

Where the file is served from. Use it in configs, themes and pages.

string format: uri
filename
required
string
contentType
required
string
sizeBytes

Set once the upload is confirmed.

integer | null
folderId
required
string | null
sourceUrl

The URL an imported file came from.

string | null
importStatus

Null for uploaded files.

string | null
Allowed values: pending failed done
importError
string | null
importAttempts
integer
createdAt
required
string format: date-time
updatedAt
string format: date-time
confirmedAt

When the file became available. Null while it is still uploading or importing.

string | null format: date-time
Example
{
"upload": {
"url": "https://uploads.example.com/",
"fields": {
"key": "example/autumn-banner.png",
"Content-Type": "image/png",
"policy": "eyJleGFtcGxlIjp0cnVlfQ==",
"signature": "c2lnbmF0dXJlLWV4YW1wbGU="
}
},
"asset": {
"id": "0192f3a1-0000-7000-8000-0000000f2001",
"url": "https://cdn.example.com/media/autumn-banner.png",
"filename": "autumn-banner.png",
"contentType": "image/png",
"sizeBytes": null,
"folderId": "0192f3a1-0000-7000-8000-0000000f1001",
"sourceUrl": null,
"importStatus": null,
"importError": null,
"importAttempts": 0,
"createdAt": "2026-10-05T10:00:00.000Z",
"updatedAt": "2026-10-05T10:00:00.000Z",
"confirmedAt": null
}
}

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."
}
}