REST API · v1

Koopi Developer API

Build on top of Koopi. The REST API powers the viewer experience, the creator upload pipeline, and platform automation over predictable JSON endpoints.

Introduction

The Koopi API is organized around REST. It has predictable resource-oriented URLs, accepts and returns JSON-encoded payloads, and uses standard HTTP response codes, verbs, and authentication. All endpoints are served from the same origin as the application.

Resource-oriented

Predictable URLs grouped by resource such as coins, series, and uploads.

JSON everywhere

Requests and responses use JSON with UTF-8 encoding.

Token & session auth

Use a scoped API token for automation, or a secure session cookie in the browser.

Standard semantics

Conventional HTTP verbs and status codes for every operation.

Base URL

All API routes are relative to your Koopi deployment origin. Prefix every path below with your base URL.

https://koopi.tv/api

Authentication

Koopi supports two ways to authenticate. In the browser, requests use a secure, HTTP-only session cookie issued at sign-in. For scripts, CI pipelines, and integrations, use an API token sent as a Bearer credential. Each endpoint declares one of three access levels:

Public

No authentication required.

User

Requires a signed-in viewer. Returns 401 otherwise.

Creator

Requires a creator account. Authenticate with a session cookie or an API token holding the required scope. Returns 401 without valid credentials and 403 when the account is not a creator or the token is missing a required scope.

API tokens

Creators can mint API tokens from the token dashboard or the Creator Hub. A token is shown only once at creation — Koopi stores just a hash, so copy it immediately. Pass it in the Authorization header:

curl https://koopi.tv/api/creator-hub/series \
  -H "Authorization: Bearer koopi_sk_xxxxxxxxxxxxxxxxxxxx"

Each token is granted one or more scopes. A request to a creator endpoint is rejected with 403 if the token lacks the scope that endpoint requires. Tokens may optionally expire and can be revoked at any time.

ScopeGrants
readRead your series, episodes, and performance data.
uploadRequest pre-signed upload URLs and push new video/image assets.
writeRegister episodes and update content metadata.

Requests & Responses

Send request bodies as JSON with a Content-Type: application/json header. Path parameters are shown in braces, for example /api/creator-hub/series/{id}. Successful responses return a 2xx status with a JSON body.

Errors

Koopi uses conventional HTTP status codes. Failures return a JSON body with an error message.

StatusMeaning
200 / 201The request succeeded.
400Malformed request or missing required parameters.
401Not authenticated — sign in and retry.
403Authenticated but lacking the required (creator) access.
404The requested resource does not exist.
429Too many requests — slow down and retry later.
5xxAn unexpected error occurred on the server.
401 Unauthorized
{
  "error": "Unauthorized"
}

Rate Limits

Endpoints are rate limited to protect platform stability. If you exceed the limit you will receive a429 response; back off and retry with exponential delay. Upload part-signing requests are batched to minimize round trips.

API Reference

Coins & Wallet

Read a viewer’s coin balance and spend coins to unlock episodes or skip advertising.

GET/api/coins/balanceUser

Return the authenticated viewer’s current coin balance.

{
  "coin_balance": 240
}
GET/api/coins/settingsUser

Fetch the coin pricing table and auto-skip configuration for the current account.

POST/api/coins/deductUser

Spend coins to unlock a locked episode or skip an ad break.

ParameterTypeDescription
amount*integerNumber of coins to deduct. Must be positive.
reason*stringOne of `unlock_episode` or `skip_ad`.
episodeIdstringSanity document id of the episode being unlocked.
POST /api/coins/deduct
{
  "amount": 30,
  "reason": "unlock_episode",
  "episodeId": "ep_9f2c..."
}
POST/api/coins/auto-skipUser

Enable or disable automatically spending coins to skip ads.

ParameterTypeDescription
enabled*booleanWhether auto-skip is turned on.

Watchlist

Manage the series a viewer has saved to watch later.

GET/api/watchlistUser

List every series in the viewer’s watchlist.

POST/api/watchlistUser

Add or remove a series from the watchlist.

ParameterTypeDescription
seriesId*stringSanity document id of the series.
action*stringEither `add` or `remove`.

Watch History

Track and resume playback progress across episodes.

GET/api/watch-historyUser

Return recently watched episodes with resume positions.

POST/api/watch-historyUser

Record playback progress for an episode.

ParameterTypeDescription
episodeId*stringEpisode being watched.
positionSeconds*numberCurrent playhead position in seconds.
completedbooleanSet true when the episode finished playing.

Leaderboard

Public ranking data for games and creators.

GET/api/leaderboardPublic

Return the top-ranked entries. Supports optional filtering by game.

ParameterTypeDescription
gameIdstringRestrict results to a single game.
limitintegerMaximum entries to return (default 50).

Series & Episodes

Creator-scoped read access to the series catalog and their episodes.

GET/api/creator-hub/seriesCreator

List all series owned by the authenticated creator.

GET/api/creator-hub/series/{id}Creator

Fetch a single series with its metadata.

ParameterTypeDescription
id*stringSeries document id (path parameter).
GET/api/creator-hub/series/{id}/episodesCreator

List every episode belonging to a series, including processing status.

ParameterTypeDescription
id*stringSeries document id (path parameter).
DELETE/api/creator-hub/episode/{id}Creator

Delete an episode. Used to abandon a source that failed or is still processing.

ParameterTypeDescription
id*stringEpisode document id (path parameter).

Media Uploads

Upload video sources and thumbnails to storage, then register them for transcoding. Large files (over 100 MB) use S3 multipart uploads for resilient, parallel transfer up to 200 GB.

POST/api/creator-hub/presignCreator

Get a pre-signed PUT URL for a single-request upload of a small video file.

ParameterTypeDescription
seriesId*stringOwning series.
episodeTitle*stringTitle used to derive the object key.
filename*stringOriginal file name.
contentType*stringMIME type, e.g. `video/mp4`.
POST/api/creator-hub/presign-imageCreator

Get a pre-signed PUT URL for uploading a thumbnail or cover image.

POST/api/creator-hub/multipart/createCreator

Begin a multipart upload. Returns the object key and an uploadId for the session.

POST /api/creator-hub/multipart/create
{
  "seriesId": "series_1a2b...",
  "episodeTitle": "Beard Talk — Episode 4",
  "filename": "beard-talk-04.mp4",
  "contentType": "video/mp4",
  "isLongForm": true
}

→ 200 OK
{
  "key": "koopi-series/.../beard-talk-04.mp4",
  "uploadId": "2~aBc..."
}
POST/api/creator-hub/multipart/sign-partsCreator

Return pre-signed PUT URLs for a batch of part numbers within an active upload.

ParameterTypeDescription
key*stringObject key from `create`.
uploadId*stringMultipart upload id.
partNumbers*integer[]Part numbers to sign (1-indexed).
POST/api/creator-hub/multipart/completeCreator

Finalize a multipart upload. Part ETags are collected server-side, so no ETag headers are required from the client.

ParameterTypeDescription
key*stringObject key from `create`.
uploadId*stringMultipart upload id.
expectedParts*integerNumber of parts uploaded, used to validate completeness.
POST/api/creator-hub/multipart/abortCreator

Cancel an in-progress multipart upload and discard any uploaded parts.

ParameterTypeDescription
key*stringObject key from `create`.
uploadId*stringMultipart upload id.
POST/api/creator-hub/register-episodeCreator

Register an uploaded source as an episode and submit it to the transcoding pipeline. Playback becomes available once processing completes.

ParameterTypeDescription
seriesId*stringOwning series.
s3Key*stringObject key of the uploaded source.
episodeTitle*stringDisplay title.
isLongFormbooleanWhether this is a long-form source for the clipper.

AI Clipper

Analyze a long-form source and generate short vertical clips from it.

POST/api/creator-hub/clipper/analyze-cutsCreator

Detect candidate cut points and highlight moments in a source.

POST/api/creator-hub/clipper/analyze-segmentsCreator

Group transcript segments into coherent clip suggestions.

POST/api/creator-hub/clipper/analyze-framingCreator

Suggest vertical framing / crop windows for a clip.

GET/api/creator-hub/clipper/shortsCreator

List generated shorts for a source.

DELETE/api/creator-hub/clipper/shorts/{id}Creator

Delete a generated short.

ParameterTypeDescription
id*stringShort document id (path parameter).

Games

Register playable game bundles and manage play sessions.

POST/api/games/registerCreator

Register an uploaded game bundle.

POST/api/games/presignCreator

Get a pre-signed URL to upload a game bundle archive.

GET/api/games/bundle-urlUser

Resolve a signed, time-limited URL to load a game bundle.

POST/api/games/sessionUser

Start or update a game play session.

POST/api/games/toggle-ad-freeUser

Toggle ad-free play using coins.

Advertising

Serve advertisements and record impression / interaction telemetry.

GET/api/ads/randomPublic

Return a randomly selected eligible advertisement.

POST/api/ads/impressionPublic

Record that an ad was shown.

ParameterTypeDescription
adId*stringAdvertisement id.
POST/api/ads/eventPublic

Record an ad interaction such as a click or skip.

ParameterTypeDescription
adId*stringAdvertisement id.
type*stringEvent type, e.g. `click` or `skip`.

Webhooks

Inbound endpoints invoked by external services. These are not called by your integration — they are secured by provider signatures and documented here for completeness.

POST/api/webhooks/muxPublic

Receives transcoding lifecycle events (asset ready, errored, track ready). Verified with the Mux signing secret.

POST/api/webhooks/s3Public

Receives storage notifications for uploaded objects.

POST/api/stripe/webhookPublic

Receives Stripe payment and checkout events. Verified with the Stripe signing secret.