neowire Public APIv1.0.0
https://api.neowire.aiAuthorization: Bearer <token>Applied per endpoint.
The client-facing API for neowire. Authenticated with the user bearer token the publisher's backend mints through the Publisher API.
Error handling#
Every endpoint declares a default response carrying this envelope (29 operations). Endpoint-specific status codes are listed with each endpoint.
errorstringcodestringMachine-readable error code; omitted when the error has none.
{
"error": "string",
"code": "string"
}Jump to an endpoint
- GET
/v1/feed - POST
/v1/feed/events - GET
/v1/user - GET
/v1/user/videos - GET
/v1/user/creators - GET
/v1/user/games - GET
/v1/user/comics - GET
/v1/videos/{uid} - POST
/v1/videos/{uid}/share - POST
/v1/videos/{uid}/unlike - POST
/v1/videos/{uid}/report - GET
/v1/creators/{creator_tag} - PATCH
/v1/creators/{creator_tag}/follow - GET
/v1/creators/{creator_tag}/videos - GET
/v1/games - GET
/v1/games/{game_id} - POST
/v1/games/{game_id}/play - POST
/v1/games/{game_id}/shop - POST
/v1/games/{game_id}/rating - GET
/v1/games/{game_id}/leaderboard - POST
/v1/games/{game_id}/share - GET
/v1/comics/{comic_id} - GET
/v1/comics/{comic_id}/parts/{part_index} - POST
/v1/comics/{comic_id}/parts/{part_index}/read - POST
/v1/comics/{comic_id}/parts/{part_index}/rating - POST
/v1/comics/{comic_id}/share - GET
/v1/shares/{id} - POST
/v1/ads - PATCH
/v1/ads/{id}
Endpoints29
/v1/feed#getFeedGet personalized video feed
Returns the next batch of videos for the user. If no session_id is provided, a new session is created. Pure read endpoint — events must be posted via POST/v1/feed/events. The user is identified by the bearer token; demographics come from the record stored at POST/s2s/v1/user/{id}/auth.
Videos are always served, no matter how much the user has already watched today. Once the daily watchtime-reward limit is reached, watchtime_rewards_available_after carries the moment rewards resume.
| Status | Code | Meaning |
|---|---|---|
| 410 | session_not_found | The referenced session does not exist. |
| 410 | session_expired | The session has expired. |
Query parameters
session_idstring · uuidearning_modestringControls earning intensity for the session: ad cadence, ad lock duration, earning multiplier, and external ad sub-type. Stored on the session; when it changes between calls, the session is updated to the latest value.
lownormalhigh
Responses
200Feed response with recommendationsGetFeedResponseapplication/json
session_idstring · uuidrequiredtotal_earnings_local_currencystringrequiredThe session's total earnings so far, with base and bonus summed into a single amount. Together with its PostFeedEventsResponse counterpart this is deliberately the only earnings field that is a plain string rather than a Reward object: the session total is rendered as one running counter, and the base/bonus breakdown is only meaningful on individual rewards, where it is exposed.
next_earning_progressnumberrequiredProgress towards the next earning (0-1)
watchtime_rewards_available_afterstring · date-time | nullrequiredWhen watch time starts earning again, or null while it still earns. Set once the user has reached the daily watchtime-reward limit: videos keep being served and events keep being accepted, but the watch time in them is no longer rewarded until this moment.
itemsarray of GetFeedItemrequired
item_type = "video" GetFeedVideoItem
item_typestringrequiredidstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredThe requesting user's friends who liked this video, most recently liked first.
user_likedbooleanrequireddeprecatedUse liked_at instead.
item_type = "ad" GetFeedAdItem
item_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
item_type = "game" GetFeedGameItem
item_typestringrequiredidstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
highscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
The requesting user's friends who have played this game, with each friend's highscore, best first.
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
item_type = "comic" GetFeedComicItem
item_typestringrequiredidstringrequiredtitlestringrequireddescriptionstringrequiredcover_urlstringrequiredparts_countintegerrequiredThe total number of parts in the comic.
read_countinteger · int64requiredTotal number of finished part-reads of this comic across all users.
rating_countinteger · int64requiredTotal number of 1-5 star ratings across all of this comic's parts. Reported as 0 (together with rating_avg) until the comic has collected at least 5 part ratings in total.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0) across all of this comic's part ratings, truncated to one decimal place. Reported as 0 until the comic has collected at least 5 part ratings (see rating_count).
read_time_avgnumber · doublerequiredSum of the per-part median read times, in seconds (reads over one hour are excluded as outliers). 0 when none of the comic's parts have been read.
Depending on the request, this may contain all parts or only the next part the user has not read yet.
The requesting user's friends who have read at least one part of this comic, furthest read first.
410Session not found or expiredGetFeedSessionErrorapplication/json
errorstringrequiredcodestringrequiredsession_not_foundsession_expired
/v1/feed/events#postFeedEventsSubmit video feed interaction events
Processes user interaction events (likes, unlikes, watch time) against an existing session. Returns the updated earnings state. The request that crosses the daily watch-time limit is rewarded only for the watch time that still fits within it. From then on events keep being accepted and recorded, but the watch time in them earns nothing until watchtime_rewards_available_after, which every response carries once the limit is reached.
When the user is not eligible for rewards (as recorded at POST/s2s/v1/user/{id}/auth), all video_watch_time events in the request body are silently discarded before processing. Likes and unlikes are still applied. No watchtime accumulates and no reward callback fires.
| Status | Code | Meaning |
|---|---|---|
| 410 | session_not_found | The referenced session does not exist. |
| 410 | session_expired | The session has expired. |
Request bodyrequiredapplication/json
session_idstring · uuidrequiredeventsarray of PostFeedEventrequired
typestringrequiredvideo_likevideo_unlikevideo_watch_time
video_idstring · uuidrequiredwatch_secondsnumber · doubletimestampstring · date-timerequiredResponses
200Events processedPostFeedEventsResponseapplication/json
session_idstring · uuidrequiredtotal_earnings_local_currencystringrequiredThe session's total earnings so far, with base and bonus summed into a single amount. Plain string instead of a Reward object — see GetFeedResponse for the rationale.
earned_local_currencyReward | nullrequired
Local currency earned this request, or null if nothing was earned.
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
next_earning_progressnumberrequiredProgress towards the next earning (0-1)
watchtime_rewards_available_afterstring · date-time | nullrequiredWhen watch time starts earning again, or null while it still earns. The request that reaches the daily watchtime-reward limit is the first to carry it, so no further earning is expected until this moment.
410Session not found or expiredGetFeedSessionErrorapplication/json
errorstringrequiredcodestringrequiredsession_not_foundsession_expired
/v1/user#getUserGet the authenticated user's profile
Responses
200User profileGetUserProfileResponseapplication/json
watchtime_streakGetUserProfileWatchtimeStreakrequired
day_countintegerrequiredCurrent streak length in completed days (0 when there is no active streak).
bonus_percentageintegerrequiredReward bonus percent applied once the streak reaches the threshold.
day_count_thresholdintegerrequiredCompleted days required before the bonus activates.
required_daily_minutesintegerrequiredMinutes the user must watch each day to complete the day and keep the streak alive. Taken from the active streak's snapshot, or the live config default when no active streak exists.
completed_todaybooleanrequiredWhether the user has already completed today's watch requirement.
minutes_until_completeinteger | nullrequiredMinutes left to watch today to advance the streak. Null if completed today or no active streak exists.
fails_in_minutesinteger | nullrequiredMinutes until the streak fails if no further day is completed. Null if completed today or no active streak exists.
/v1/user/videos#listUserVideosList videos liked by the user
Returns a paginated list of videos the user has liked, ordered by the time of the like (newest first). Cursor is the RFC3339Nano timestamp of the last item's liked_at.
Query parameters
cursorstringlimitintegerResponses
200Paginated liked videosListUserVideosResponseapplication/json
itemsarray of Videorequired
idstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredThe requesting user's friends who liked this video, most recently liked first.
next_cursorstring | nullrequiredCursor for the next page (RFC3339Nano timestamp), null if no more items.
/v1/user/creators#listUserCreatorsList creators followed by the user
Returns the creators followed by the user, ordered by most recent follow first.
Responses
200OKListUserCreatorsResponseapplication/json
itemsarray of Creatorrequired
tagstringrequiredThe creator's unique tag (username / public identifier).
namestringrequiredThe creator's display name; falls back to the tag when unset.
biostringrequiredpicture_urlstring | nullrequiredProfile picture URL; null when the creator has none set.
picture_stylestringrequiredHow the client should render the profile picture — "circle" (round avatar mask) or "cover" (full-bleed image, no mask).
circlecover
followed_atstring · date-time | nullrequiredTimestamp when the requesting user followed this creator; null when not followed.
video_countinteger · int64requiredfollowers_countinteger · int64required/v1/user/games#listUserGamesList games the user has played
Returns the games the user has at least one recorded event for, ordered by most recent event first. The user is identified by the bearer token.
Responses
200Games the user has playedListUserGamesResponseapplication/json
gamesarray of Gamerequired
idstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
highscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
The requesting user's friends who have played this game, with each friend's highscore, best first.
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
/v1/user/comics#listUserComicsList the user's comics
Returns a list of the user's comics, ordered by most recent comic first.
Responses
200User's comicsListUserComicsResponseapplication/json
itemsarray of Comicrequired
Each item only contains the next part the user has not ready yet or the last part of the comic.
idstringrequiredtitlestringrequireddescriptionstringrequiredcover_urlstringrequiredparts_countintegerrequiredThe total number of parts in the comic.
read_countinteger · int64requiredTotal number of finished part-reads of this comic across all users.
rating_countinteger · int64requiredTotal number of 1-5 star ratings across all of this comic's parts. Reported as 0 (together with rating_avg) until the comic has collected at least 5 part ratings in total.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0) across all of this comic's part ratings, truncated to one decimal place. Reported as 0 until the comic has collected at least 5 part ratings (see rating_count).
read_time_avgnumber · doublerequiredSum of the per-part median read times, in seconds (reads over one hour are excluded as outliers). 0 when none of the comic's parts have been read.
Depending on the request, this may contain all parts or only the next part the user has not read yet.
The requesting user's friends who have read at least one part of this comic, furthest read first.
/v1/videos/{uid}#getVideoGet a video
Returns a single video by its id, including the requesting user's like state (liked_at) and which of their friends liked it.
| Status | Code | Meaning |
|---|---|---|
| 404 | video_not_found | The video does not exist or was deleted. |
Path parameters
uidstring · uuidrequiredResponses
200VideoVideoapplication/json
idstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredfriend_likesarray of VideoFriendLikerequired
The requesting user's friends who liked this video, most recently liked first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
liked_atstring · date-timerequiredWhen the friend liked the video.
/v1/videos/{uid}/unlike#unlikeVideoRemove a user's like from a video
Removes the user's like for a video outside the session-event flow. Idempotent - unliking a video the user has not liked succeeds.
Path parameters
uidstring · uuidrequiredResponses
204Like removed (or did not exist)
No response body.
/v1/videos/{uid}/report#reportVideoReport a video
Records a user report for a video. Only one report per user & video is stored.
| Status | Code | Meaning |
|---|---|---|
| 404 | video_not_found | The video does not exist or was deleted. |
Path parameters
uidstring · uuidrequiredRequest bodyrequiredapplication/json
reasonstringrequiredsexual_contentviolent_or_repulsive_contenthateful_or_abusive_contentharassment_or_bullyingharmful_or_dangerous_actssuicide_self_harm_or_eating_disorders+5 more
misinformationchild_abusepromotes_terrorismspam_or_misleadinglegal_issue
Responses
204Report recorded (or already existed)
No response body.
/v1/creators/{creator_tag}#getCreatorGet a creator by tag
Returns the creator's metadata, including whether the requesting user follows them (followed_at).
| Status | Code | Meaning |
|---|---|---|
| 404 | creator_not_found | The creator does not exist. |
Path parameters
creator_tagstringrequiredThe creator's tag.
Responses
200Creator metadataCreatorapplication/json
tagstringrequiredThe creator's unique tag (username / public identifier).
namestringrequiredThe creator's display name; falls back to the tag when unset.
biostringrequiredpicture_urlstring | nullrequiredProfile picture URL; null when the creator has none set.
picture_stylestringrequiredHow the client should render the profile picture — "circle" (round avatar mask) or "cover" (full-bleed image, no mask).
circlecover
followed_atstring · date-time | nullrequiredTimestamp when the requesting user followed this creator; null when not followed.
video_countinteger · int64requiredfollowers_countinteger · int64requiredlinksarray of CreatorLinkrequired
textstringrequiredurlstringrequired/v1/creators/{creator_tag}/follow#followCreatorFollow/Unfollow a creator
Follows or unfollows the creator. Idempotent in both directions.
| Status | Code | Meaning |
|---|---|---|
| 404 | creator_not_found | The creator does not exist. |
Path parameters
creator_tagstringrequiredThe creator's tag.
Request bodyrequiredapplication/json
actionstringrequiredfollowunfollow
Responses
204Follow status updated
No response body.
/v1/creators/{creator_tag}/videos#listCreatorVideosList videos by creator
Returns a paginated list of videos uploaded by the specified creator. The cursor is the id (UUID) of the last video from the previous page's next_cursor; pass it verbatim to fetch the following page.
| Status | Code | Meaning |
|---|---|---|
| 404 | creator_not_found | The creator does not exist. |
Path parameters
creator_tagstringrequiredThe creator's tag.
Query parameters
cursorstringlimitintegerResponses
200List of videosListCreatorVideosResponseapplication/json
itemsarray of Videorequired
idstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredThe requesting user's friends who liked this video, most recently liked first.
next_cursorstring | nullrequiredThe last video's id (UUID), used as the next page's cursor; null if no more items.
/v1/games#listGamesList public games
Returns the generally available game catalog without user-specific state. This endpoint does not require authentication.
Responses
200Public game catalogListGamesResponseapplication/json
itemsarray of Gamerequired
idstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
highscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
The requesting user's friends who have played this game, with each friend's highscore, best first.
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
/v1/games/{game_id}#getGameGet a game and its events for the user
gamesReturns the game's metadata and the events of the version the user is on: the latest version if the user has not completed any event for this game yet, otherwise the version of the user's first completed event (so progress stays stable when new versions are published).
| Status | Code | Meaning |
|---|---|---|
| 404 | game_not_found | The game does not exist or was deleted. |
Path parameters
game_idstringrequiredResponses
200Game with eventsGameapplication/json
idstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
eventsarray of GameEventrequired
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredthreshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredmissionsarray of GameMissionrequired
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringstatusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
highscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
stateGameStaterequired
friend_highscoresarray of GameFriendHighscorerequired
The requesting user's friends who have played this game, with each friend's highscore, best first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
highscoreintegerrequiredThe friend's best result for this game (highest level for level games, highest score for highscore games).
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
/v1/games/{game_id}/play#postGamePlayTrack a game play
gamesRecords a client game play (one game_end). score is null on game over; for level games it is the level reached, for highscore games the score achieved. playtime_seconds is the whole seconds played since the previous submission. state_change optionally carries per-value operations (see state_change) that are applied to the user's running game state, which the response returns as state.
A round the client continues — after granting a second life, say — is submitted again with previous_play_id set to the play_id the previous submission returned. Each submission carries only what happened since the one before it, of playtime and state alike, never a running total; score is the exception and stays the round's best so far. A round may be continued at most 5 times.
A submission carrying an idempotency_key — a UUID the client stamps on it, fresh per submission and the same across every retry of it — is recorded once however often it arrives: each repeat returns the recorded submission's play_id and the user's current state, completing and rewarding nothing further. A key is scoped to the caller and the game, so it only has to be unique among that user's own submissions for this game; it is shared with the shop endpoint. Omit the key to have every request recorded on its own.
| Status | Code | Meaning |
|---|---|---|
| 404 | game_not_found | The game does not exist or was deleted. |
| 400 | invalid_state_change | A state_change value is unknown, carries an operation its type does not support, or is out of range. |
| 404 | play_not_found | previous_play_id does not name a play of this game belonging to the caller. |
| 409 | play_superseded | previous_play_id is no longer the caller's most recent play of the game, so its round is over. |
| 409 | play_chain_exhausted | The round has already been continued 5 times. |
Path parameters
game_idstringrequiredRequest bodyrequiredapplication/json
scoreinteger | nullrequiredLevel reached (level games) or score achieved (highscore games). Null on game over.
playtime_secondsintegerrequiredWhole seconds the client played since the previous submission, so a continued round's submissions each carry their own slice rather than the round's total.
idempotency_keystring · uuidprevious_play_idstring · uuidThe play_id of the submission this one continues, when the client is resuming a round rather than starting one. It must be the caller's most recent play of this game — a shop transaction in between does not end a round — and a round may be continued at most 5 times. Omit to start a new round.
state_changemap<string, PostGamePlayStateDelta>
Per-value state changes keyed by value name (may be empty or omitted). Each name must be configured on the game and each operation must be one the value's type supports; anything else returns 400 invalid_state_change. The changes are applied to the user's running state snapshot for this game, which the response returns as state.
«key»PostGamePlayStateDelta
incrementinteger · int64Amount to add to a counter (non-negative) or gauge value this play. A gauge takes either sign, so a negative increment is how it moves down.
change_stringstringThe new value of a string value, overriding whatever was stored. Must match the value's configured pattern.
change_booleanbooleanThe new value of a boolean value, overriding whatever was stored.
change_numbernumber · doubleThe new value of a number value, overriding whatever was stored.
set_addarray of stringElements to add to a set value. Each must be one of the value's configured elements.
set_removearray of stringElements to drop from a set value. Each must be one of the value's configured elements and may not also be added.
list_addarray of anyItems to append to a list value, each shaped by the value's configured item schema.
list_removearray of integerPositions to drop from a list value, as indices into the list as it was before this play.
list_replacearray of PostGamePlayStateReplaceItems to overwrite in a list value.
placementstringWhere the play occurred: inside the video feed or the dedicated games tab. Defaults to feed when omitted.
feedgames_tab
Responses
200Play trackedPostGamePlayResponseapplication/json
play_idstring · uuid | nullrequiredHandle of the submission just recorded, to send back as previous_play_id when continuing this round. Null when the play was dropped (duplicate submission, rate limit): nothing was recorded, so there is nothing to continue.
stateGameStaterequired
The user's game state after this play, with every configured value present. Returned unchanged when the play was dropped (duplicate submission, rate limit), so the client can always reconcile against it.
earned_local_currencyReward | nullrequired
Local currency earned this request, or null if nothing was earned.
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
completed_eventsarray of GameEventrequired
Events completed this request.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredthreshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredcompleted_missionsarray of GameMissionrequired
Missions completed this request.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringstatusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
adAd | nullrequired
An ad to show, served on a fixed cadence; null otherwise.
slot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
/v1/games/{game_id}/shop#postGameShopRecord an in-game shop transaction
gamesApplies a state change that came from the game's own shop — an upgrade bought, a skin unlocked — rather than from playing. Use this instead of a scoreless play: a transaction counts toward no play count, leaderboard, playtime total or games-played goal, and is not part of a round, so it can neither be continued nor continue one.
It does contribute the state it grants. An event watching a counter, gauge or set can complete on it, and an ongoing mission is advanced and can complete — but a transaction never starts a mission, and never reaches a goal that measures a round (level, highscore, games_played, or any goal with a playtime cap). Those complete on the user's next play instead.
A transaction carrying an idempotency_key — a UUID the client stamps on it, fresh per transaction and the same across every retry of it — is applied once however often it arrives: each repeat returns the user's current state, completing and rewarding nothing further. A key is scoped to the caller and the game, so it only has to be unique among that user's own submissions for this game; it is shared with the play endpoint. Omit the key to have every request applied on its own.
| Status | Code | Meaning |
|---|---|---|
| 404 | game_not_found | The game does not exist or was deleted. |
| 400 | invalid_state_change | A state_change value is unknown, carries an operation its type does not support, or is out of range. |
| 429 | shop_rate_limited | More than 120 transactions for this game within the hour. Unlike a rate-limited play, this is refused rather than silently dropped. |
Path parameters
game_idstringrequiredRequest bodyrequiredapplication/json
state_changemap<string, PostGamePlayStateDelta>required
Per-value state changes keyed by value name, in the same form the play endpoint takes and held to the same per-value bounds. These are the values the purchase moved.
«key»PostGamePlayStateDelta
incrementinteger · int64Amount to add to a counter (non-negative) or gauge value this play. A gauge takes either sign, so a negative increment is how it moves down.
change_stringstringThe new value of a string value, overriding whatever was stored. Must match the value's configured pattern.
change_booleanbooleanThe new value of a boolean value, overriding whatever was stored.
change_numbernumber · doubleThe new value of a number value, overriding whatever was stored.
set_addarray of stringElements to add to a set value. Each must be one of the value's configured elements.
set_removearray of stringElements to drop from a set value. Each must be one of the value's configured elements and may not also be added.
list_addarray of anyItems to append to a list value, each shaped by the value's configured item schema.
list_removearray of integerPositions to drop from a list value, as indices into the list as it was before this play.
list_replacearray of PostGamePlayStateReplaceItems to overwrite in a list value.
idempotency_keystring · uuidplacementstringWhere the game was running when the transaction happened: inside the video feed or the dedicated games tab. Defaults to feed when omitted.
feedgames_tab
Responses
200Transaction recordedPostGameShopResponseapplication/json
stateGameStaterequired
The user's game state after the transaction, with every configured value present.
earned_local_currencyReward | nullrequired
Local currency earned this request, or null if nothing was earned.
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
completed_eventsarray of GameEventrequired
Events the transaction completed.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredthreshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredcompleted_missionsarray of GameMissionrequired
Missions the transaction completed.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringstatusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
/v1/games/{game_id}/rating#rateGameRate a game
gamesSubmits the user's 1-5 star rating for a game. A user may only rate a game they have played (at least one recorded play) and each user can rate a game exactly once — the rating is immutable and cannot be changed or resubmitted.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_rating | rating is outside the 1-5 range. |
| 403 | not_played | The user has not played this game yet. |
| 404 | game_not_found | The game does not exist or was deleted. |
| 409 | already_rated | The user has already rated this game. |
Path parameters
game_idstringrequiredRequest bodyrequiredapplication/json
ratingintegerrequiredThe rating in whole stars, from 1 to 5. Values outside this range are rejected with invalid_rating.
Responses
204Rating recorded
No response body.
/v1/games/{game_id}/leaderboard#getGameLeaderboardGet a game's leaderboard
gamesReturns the top 50 users for the game ranked by their best score: the highest level reached for level games, the highest score achieved for highscore games. Each entry carries the user's rank, username, picture url and score.
| Status | Code | Meaning |
|---|---|---|
| 404 | game_not_found | The game does not exist or was deleted. |
Path parameters
game_idstringrequiredResponses
200Game leaderboardGetGameLeaderboardResponseapplication/json
ranksarray of GameLeaderboardRankrequired
The top 50 users for the game, ordered by rank ascending. Users without a username are left out - except the requesting user themselves, who is always listed at their own position when they have one, so an unnamed user sees their rank without appearing on anyone else's board.
rankinteger | nullrequired1-based position in the leaderboard; null in user_rank when the user is not in the top 50.
usernamestringrequiredpicture_urlstringrequiredscoreintegerrequiredBest level (level games) or best score (highscore games); 0 if never played.
user_rankGameLeaderboardRankrequired
rankinteger | nullrequired1-based position in the leaderboard; null in user_rank when the user is not in the top 50.
usernamestringrequiredpicture_urlstringrequiredscoreintegerrequiredBest level (level games) or best score (highscore games); 0 if never played.
/v1/comics/{comic_id}#getComicGet a comic
Retrieves a comic by its ID.
| Status | Code | Meaning |
|---|---|---|
| 404 | comic_not_found | The comic does not exist or was deleted. |
Path parameters
comic_idstringrequiredResponses
200ComicComicapplication/json
idstringrequiredtitlestringrequireddescriptionstringrequiredcover_urlstringrequiredparts_countintegerrequiredThe total number of parts in the comic.
read_countinteger · int64requiredTotal number of finished part-reads of this comic across all users.
rating_countinteger · int64requiredTotal number of 1-5 star ratings across all of this comic's parts. Reported as 0 (together with rating_avg) until the comic has collected at least 5 part ratings in total.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0) across all of this comic's part ratings, truncated to one decimal place. Reported as 0 until the comic has collected at least 5 part ratings (see rating_count).
read_time_avgnumber · doublerequiredSum of the per-part median read times, in seconds (reads over one hour are excluded as outliers). 0 when none of the comic's parts have been read.
partsarray of ComicPartrequired
Depending on the request, this may contain all parts or only the next part the user has not read yet.
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
friend_reading_progressarray of ComicFriendReadingProgressrequired
The requesting user's friends who have read at least one part of this comic, furthest read first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
last_read_part_indexintegerrequiredThe highest part index the friend has read in this comic.
/v1/comics/{comic_id}/parts/{part_index}#getComicPartGet a full comic part
Returns a single comic part with all its pages. This is the only comic endpoint that populates pages and creates the part's server-side ad slots (a mid-part native ad, plus a trailing interstitial while the part is unfinished); the list/detail/feed endpoints return part metadata without pages.
Reading is sequential: only a part the user has already read or the single next readable part can be fetched. Any other part — locked, behind a still-processing gap, or an unknown index — returns part_locked.
| Status | Code | Meaning |
|---|---|---|
| 400 | part_locked | The part is locked or not visible to the user. |
| 404 | comic_not_found | The comic does not exist or was deleted. |
Path parameters
comic_idstringrequiredpart_indexintegerrequiredResponses
200Comic partComicPartapplication/json
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
rewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
pagesarray of ComicPartPagesItem | nullrequired
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
page_type = "page" ComicPartPage
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequiredpage_type = "ad" ComicPartPageAd
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
/v1/comics/{comic_id}/parts/{part_index}/read#markComicPartReadMark a comic part as read
Marks a specific part of a comic as read by the user.
| Status | Code | Meaning |
|---|---|---|
| 400 | already_read | The part is already marked as read. |
| 400 | part_locked | The part is locked and cannot be marked as read. |
| 404 | comic_not_found | The comic does not exist or was deleted. |
Path parameters
comic_idstringrequiredpart_indexintegerrequiredRequest bodyrequiredapplication/json
pagesarray of objectrequired
Per page user metrics.
indexintegerrequiredThe index of the page.
read_secondsnumber · doublerequiredThe number of seconds the user read the page.
Responses
200Part marked as readMarkComicPartReadResponseapplication/json
next_partobject | nullrequired
The next part of the comic to read, or null if there is no next part. Carries part metadata only — its pages are null; fetch them from GET /v1/comics/{comic_id}/parts/{part_index}.
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
rewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
pagesarray of ComicPartPagesItem | nullrequired
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
page_type = "page" ComicPartPage
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequiredpage_type = "ad" ComicPartPageAd
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
earned_local_currencyReward | nullrequired
Local currency earned this request, or null if nothing was earned.
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
/v1/comics/{comic_id}/parts/{part_index}/rating#rateComicPartRate a comic part
Submits the user's 1-5 star rating for a specific part of a comic. A user may only rate a part they have read and each user can rate a part exactly once — the rating is immutable and cannot be changed or resubmitted.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_rating | rating is outside the 1-5 range. |
| 403 | not_read | The user has not read this part yet. |
| 404 | comic_not_found | The comic does not exist or was deleted. |
| 409 | already_rated | The user has already rated this part. |
Path parameters
comic_idstringrequiredpart_indexintegerrequiredRequest bodyrequiredapplication/json
ratingintegerrequiredThe rating in whole stars, from 1 to 5. Values outside this range are rejected with invalid_rating.
Responses
204Rating recorded
No response body.
/v1/ads#createAdCreate a client-side ad slot
gamesRecords a client-created ad slot for the user and returns it, including the slot_id used to fill it later via PATCH/v1/ads/{id}. placement is required; the optional media_type/media_ref attribute the slot to the game the ad is shown against. Clients create feed and game placement slots; comic ads are server-managed. Feed slots reference a session rather than a specific media, so they carry no media_type/media_ref.
| Status | Code | Meaning |
|---|---|---|
| 429 | rate_limited | Too many ad slots created recently. |
Request bodyrequiredapplication/json
typestringrequiredofferexternal
external_sub_typestring | nullSub-type for external ads; null or omitted otherwise.
nativeinterstitialrewarded
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
placementstringrequiredThe placement this ad belongs to.
feedgame
media_typestring | nullThe type of media the slot references. Only game media is client-referenceable (feed and comic ads are server-managed). Null or omitted when no specific media is referenced.
media_refstring | nullThe referenced media's public id: the game's id/slug (e.g. arrow-escape). Stored as-is. Null or omitted when no specific media is referenced.
Responses
200Ad slot createdAdapplication/json
slot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
/v1/ads/{id}#fillClientAdFill a client-side ad slot
Attaches client attribution data to an ad slot the user owns. A slot can be filled exactly once. Overly long string fields are truncated and the bid is capped server-side.
| Status | Code | Meaning |
|---|---|---|
| 404 | ad_not_found | The ad slot does not exist. |
| 409 | already_filled | The ad slot has already been filled. |
Path parameters
idstring · uuidrequiredRequest bodyrequiredapplication/json
client_dataAdClientDatarequired
ad_platformstringad_sourcestringad_formatstringad_unit_namestringcurrencystringISO 4217 currency code for the bid.
bidstringBid amount as a decimal string (e.g. "1.25").
Responses
204Ad slot filled
No response body.
Schemas
GetFeedResponseobject
session_idstring · uuidrequiredtotal_earnings_local_currencystringrequiredThe session's total earnings so far, with base and bonus summed into a single amount. Together with its PostFeedEventsResponse counterpart this is deliberately the only earnings field that is a plain string rather than a Reward object: the session total is rendered as one running counter, and the base/bonus breakdown is only meaningful on individual rewards, where it is exposed.
next_earning_progressnumberrequiredProgress towards the next earning (0-1)
watchtime_rewards_available_afterstring · date-time | nullrequiredWhen watch time starts earning again, or null while it still earns. Set once the user has reached the daily watchtime-reward limit: videos keep being served and events keep being accepted, but the watch time in them is no longer rewarded until this moment.
itemsarray of GetFeedItemrequired
item_type = "video" GetFeedVideoItem
item_typestringrequiredidstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredfriend_likesarray of VideoFriendLikerequired
The requesting user's friends who liked this video, most recently liked first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
liked_atstring · date-timerequiredWhen the friend liked the video.
user_likedbooleanrequireddeprecatedUse liked_at instead.
item_type = "ad" GetFeedAdItem
item_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
item_type = "game" GetFeedGameItem
item_typestringrequiredidstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
eventsarray of GameEventrequired
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredthreshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredmissionsarray of GameMissionrequired
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringstatusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
highscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
stateGameStaterequired
friend_highscoresarray of GameFriendHighscorerequired
The requesting user's friends who have played this game, with each friend's highscore, best first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
highscoreintegerrequiredThe friend's best result for this game (highest level for level games, highest score for highscore games).
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
item_type = "comic" GetFeedComicItem
item_typestringrequiredidstringrequiredtitlestringrequireddescriptionstringrequiredcover_urlstringrequiredparts_countintegerrequiredThe total number of parts in the comic.
read_countinteger · int64requiredTotal number of finished part-reads of this comic across all users.
rating_countinteger · int64requiredTotal number of 1-5 star ratings across all of this comic's parts. Reported as 0 (together with rating_avg) until the comic has collected at least 5 part ratings in total.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0) across all of this comic's part ratings, truncated to one decimal place. Reported as 0 until the comic has collected at least 5 part ratings (see rating_count).
read_time_avgnumber · doublerequiredSum of the per-part median read times, in seconds (reads over one hour are excluded as outliers). 0 when none of the comic's parts have been read.
partsarray of ComicPartrequired
Depending on the request, this may contain all parts or only the next part the user has not read yet.
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
friend_reading_progressarray of ComicFriendReadingProgressrequired
The requesting user's friends who have read at least one part of this comic, furthest read first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
last_read_part_indexintegerrequiredThe highest part index the friend has read in this comic.
{
"session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"total_earnings_local_currency": "string",
"next_earning_progress": 0,
"watchtime_rewards_available_after": "2026-08-09T12:00:00Z",
"items": [
{
"item_type": "video",
"id": "string",
"creator_tag": "string",
"creator_name": "string",
"caption": "string",
"hls_url": "string",
"uploaded_at": "2026-08-09T12:00:00Z",
"liked_at": "2026-08-09T12:00:00Z",
"like_count": 0,
"view_count": 0,
"cta": {
"text": "string",
"url": "string"
},
"friend_likes": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"liked_at": "2026-08-09T12:00:00Z"
}
]
},
{
"item_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
},
{
"item_type": "game",
"id": "string",
"name": "string",
"icon_url": "string",
"banner_image_url": "string",
"card_image_url": "string",
"category": "arcade",
"game_url": "string",
"type": "level",
"version": 0,
"play_count": 0,
"is_in_endgame": true,
"events": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"sort_order": 0,
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"threshold_type": "level",
"blocked_by": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"marks_endgame": true,
"completed_at": "2026-08-09T12:00:00Z"
}
],
"missions": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"status": "not_started",
"joinable_until": "2026-08-09T12:00:00Z",
"minutes_to_complete": 0,
"goals": [
{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}
]
}
],
"highscore": 0,
"last_played_at": "2026-08-09T12:00:00Z",
"discovered_at": "2026-08-09T12:00:00Z",
"state": {
"key": {
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}
},
"friend_highscores": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"highscore": 0
}
],
"rating_count": 0,
"rating_avg": 0,
"user_rating": 0,
"section": "test"
},
{
"item_type": "comic",
"id": "string",
"title": "string",
"description": "string",
"cover_url": "string",
"parts_count": 0,
"read_count": 0,
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0,
"parts": [
{
"index": 0,
"version": "string",
"title": "string",
"description": "string",
"unlocked": true,
"finished_reading_at": "2026-08-09T12:00:00Z",
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"cover_url": "string",
"music_url": "string",
"pages": [
{
"page_type": "page",
"index": 0,
"video_url": "string"
},
{
"page_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}
],
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0
}
],
"friend_reading_progress": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"last_read_part_index": 0
}
]
}
]
}Showing all 4 variants of the union.
GetFeedSessionErrorobject
errorstringrequiredcodestringrequiredsession_not_foundsession_expired
{
"error": "string",
"code": "session_not_found"
}GetFeedItemoneOf · 4
item_type = "video" GetFeedVideoItem
item_typestringrequiredidstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredfriend_likesarray of VideoFriendLikerequired
The requesting user's friends who liked this video, most recently liked first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
liked_atstring · date-timerequiredWhen the friend liked the video.
user_likedbooleanrequireddeprecatedUse liked_at instead.
item_type = "ad" GetFeedAdItem
item_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
item_type = "game" GetFeedGameItem
item_typestringrequiredidstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
eventsarray of GameEventrequired
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
threshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredmissionsarray of GameMissionrequired
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
statusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
goalsarray of GameMissionGoalrequired
translationsmap<string, string>required
«key»stringvaluenumber · doublerequiredThe user's current progress toward the goal.
thresholdnumber · doublerequiredThe value at which the goal completes.
completedbooleanrequiredhighscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
stateGameStaterequired
«key»GameStateValue
totalinteger · int64A counter's or gauge's current total. Both only ever move by whole increments, so this is a whole number - exact across the full int64 range, of which a client reading it into a double can represent up to 2^53.
numbernumber · doubleA number value's current value.
stringstringA string value's current value.
booleanbooleanA boolean value's current value.
setarray of stringA set value's current elements, sorted. Always present (and empty when nothing is held) for set values.
listarray of anyA list value's current items in order, each shaped by the item schema configured for the value. Always present (and empty when nothing is held) for list values.
friend_highscoresarray of GameFriendHighscorerequired
The requesting user's friends who have played this game, with each friend's highscore, best first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
highscoreintegerrequiredThe friend's best result for this game (highest level for level games, highest score for highscore games).
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
item_type = "comic" GetFeedComicItem
item_typestringrequiredidstringrequiredtitlestringrequireddescriptionstringrequiredcover_urlstringrequiredparts_countintegerrequiredThe total number of parts in the comic.
read_countinteger · int64requiredTotal number of finished part-reads of this comic across all users.
rating_countinteger · int64requiredTotal number of 1-5 star ratings across all of this comic's parts. Reported as 0 (together with rating_avg) until the comic has collected at least 5 part ratings in total.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0) across all of this comic's part ratings, truncated to one decimal place. Reported as 0 until the comic has collected at least 5 part ratings (see rating_count).
read_time_avgnumber · doublerequiredSum of the per-part median read times, in seconds (reads over one hour are excluded as outliers). 0 when none of the comic's parts have been read.
partsarray of ComicPartrequired
Depending on the request, this may contain all parts or only the next part the user has not read yet.
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
rewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
pagesarray of ComicPartPagesItem | nullrequired
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
page_type = "page" ComicPartPage
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequiredpage_type = "ad" ComicPartPageAd
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
friend_reading_progressarray of ComicFriendReadingProgressrequired
The requesting user's friends who have read at least one part of this comic, furthest read first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
last_read_part_indexintegerrequiredThe highest part index the friend has read in this comic.
{
"item_type": "video",
"id": "string",
"creator_tag": "string",
"creator_name": "string",
"caption": "string",
"hls_url": "string",
"uploaded_at": "2026-08-09T12:00:00Z",
"liked_at": "2026-08-09T12:00:00Z",
"like_count": 0,
"view_count": 0,
"cta": {
"text": "string",
"url": "string"
},
"friend_likes": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"liked_at": "2026-08-09T12:00:00Z"
}
]
}Showing the video variant.
GetFeedVideoItemallOf
item_typestringrequiredidstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredfriend_likesarray of VideoFriendLikerequired
The requesting user's friends who liked this video, most recently liked first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
liked_atstring · date-timerequiredWhen the friend liked the video.
user_likedbooleanrequireddeprecatedUse liked_at instead.
{
"item_type": "video",
"id": "string",
"creator_tag": "string",
"creator_name": "string",
"caption": "string",
"hls_url": "string",
"uploaded_at": "2026-08-09T12:00:00Z",
"liked_at": "2026-08-09T12:00:00Z",
"like_count": 0,
"view_count": 0,
"cta": {
"text": "string",
"url": "string"
},
"friend_likes": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"liked_at": "2026-08-09T12:00:00Z"
}
]
}GetFeedAdItemallOf
item_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
{
"item_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}GetFeedGameItemallOf
item_typestringrequiredidstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
eventsarray of GameEventrequired
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
threshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredmissionsarray of GameMissionrequired
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
statusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
goalsarray of GameMissionGoalrequired
translationsmap<string, string>required
«key»stringvaluenumber · doublerequiredThe user's current progress toward the goal.
thresholdnumber · doublerequiredThe value at which the goal completes.
completedbooleanrequiredhighscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
stateGameStaterequired
«key»GameStateValue
totalinteger · int64A counter's or gauge's current total. Both only ever move by whole increments, so this is a whole number - exact across the full int64 range, of which a client reading it into a double can represent up to 2^53.
numbernumber · doubleA number value's current value.
stringstringA string value's current value.
booleanbooleanA boolean value's current value.
setarray of stringA set value's current elements, sorted. Always present (and empty when nothing is held) for set values.
listarray of anyA list value's current items in order, each shaped by the item schema configured for the value. Always present (and empty when nothing is held) for list values.
friend_highscoresarray of GameFriendHighscorerequired
The requesting user's friends who have played this game, with each friend's highscore, best first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
highscoreintegerrequiredThe friend's best result for this game (highest level for level games, highest score for highscore games).
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
{
"item_type": "game",
"id": "string",
"name": "string",
"icon_url": "string",
"banner_image_url": "string",
"card_image_url": "string",
"category": "arcade",
"game_url": "string",
"type": "level",
"version": 0,
"play_count": 0,
"is_in_endgame": true,
"events": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"sort_order": 0,
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"threshold_type": "level",
"blocked_by": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"marks_endgame": true,
"completed_at": "2026-08-09T12:00:00Z"
}
],
"missions": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"status": "not_started",
"joinable_until": "2026-08-09T12:00:00Z",
"minutes_to_complete": 0,
"goals": [
{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}
]
}
],
"highscore": 0,
"last_played_at": "2026-08-09T12:00:00Z",
"discovered_at": "2026-08-09T12:00:00Z",
"state": {
"key": {
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}
},
"friend_highscores": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"highscore": 0
}
],
"rating_count": 0,
"rating_avg": 0,
"user_rating": 0,
"section": "test"
}Showing the icon variant.
GetFeedComicItemallOf
item_typestringrequiredidstringrequiredtitlestringrequireddescriptionstringrequiredcover_urlstringrequiredparts_countintegerrequiredThe total number of parts in the comic.
read_countinteger · int64requiredTotal number of finished part-reads of this comic across all users.
rating_countinteger · int64requiredTotal number of 1-5 star ratings across all of this comic's parts. Reported as 0 (together with rating_avg) until the comic has collected at least 5 part ratings in total.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0) across all of this comic's part ratings, truncated to one decimal place. Reported as 0 until the comic has collected at least 5 part ratings (see rating_count).
read_time_avgnumber · doublerequiredSum of the per-part median read times, in seconds (reads over one hour are excluded as outliers). 0 when none of the comic's parts have been read.
partsarray of ComicPartrequired
Depending on the request, this may contain all parts or only the next part the user has not read yet.
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
rewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
pagesarray of ComicPartPagesItem | nullrequired
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
page_type = "page" ComicPartPage
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequiredpage_type = "ad" ComicPartPageAd
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
friend_reading_progressarray of ComicFriendReadingProgressrequired
The requesting user's friends who have read at least one part of this comic, furthest read first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
last_read_part_indexintegerrequiredThe highest part index the friend has read in this comic.
{
"item_type": "comic",
"id": "string",
"title": "string",
"description": "string",
"cover_url": "string",
"parts_count": 0,
"read_count": 0,
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0,
"parts": [
{
"index": 0,
"version": "string",
"title": "string",
"description": "string",
"unlocked": true,
"finished_reading_at": "2026-08-09T12:00:00Z",
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"cover_url": "string",
"music_url": "string",
"pages": [
{
"page_type": "page",
"index": 0,
"video_url": "string"
},
{
"page_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}
],
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0
}
],
"friend_reading_progress": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"last_read_part_index": 0
}
]
}Showing all 2 variants of the union.
PostFeedEventsRequestobject
session_idstring · uuidrequiredeventsarray of PostFeedEventrequired
typestringrequiredvideo_likevideo_unlikevideo_watch_time
video_idstring · uuidrequiredwatch_secondsnumber · doubletimestampstring · date-timerequired{
"session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"events": [
{
"type": "video_like",
"video_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"watch_seconds": 0,
"timestamp": "2026-08-09T12:00:00Z"
}
]
}PostFeedEventobject
typestringrequiredvideo_likevideo_unlikevideo_watch_time
video_idstring · uuidrequiredwatch_secondsnumber · doubletimestampstring · date-timerequired{
"type": "video_like",
"video_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"watch_seconds": 0,
"timestamp": "2026-08-09T12:00:00Z"
}PostFeedEventsResponseobject
session_idstring · uuidrequiredtotal_earnings_local_currencystringrequiredThe session's total earnings so far, with base and bonus summed into a single amount. Plain string instead of a Reward object — see GetFeedResponse for the rationale.
earned_local_currencyReward | nullrequired
Local currency earned this request, or null if nothing was earned.
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
next_earning_progressnumberrequiredProgress towards the next earning (0-1)
watchtime_rewards_available_afterstring · date-time | nullrequiredWhen watch time starts earning again, or null while it still earns. The request that reaches the daily watchtime-reward limit is the first to carry it, so no further earning is expected until this moment.
{
"session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"total_earnings_local_currency": "string",
"earned_local_currency": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"next_earning_progress": 0,
"watchtime_rewards_available_after": "2026-08-09T12:00:00Z"
}Showing the icon variant.
GetUserProfileResponseobject
watchtime_streakGetUserProfileWatchtimeStreakrequired
day_countintegerrequiredCurrent streak length in completed days (0 when there is no active streak).
bonus_percentageintegerrequiredReward bonus percent applied once the streak reaches the threshold.
day_count_thresholdintegerrequiredCompleted days required before the bonus activates.
required_daily_minutesintegerrequiredMinutes the user must watch each day to complete the day and keep the streak alive. Taken from the active streak's snapshot, or the live config default when no active streak exists.
completed_todaybooleanrequiredWhether the user has already completed today's watch requirement.
minutes_until_completeinteger | nullrequiredMinutes left to watch today to advance the streak. Null if completed today or no active streak exists.
fails_in_minutesinteger | nullrequiredMinutes until the streak fails if no further day is completed. Null if completed today or no active streak exists.
{
"watchtime_streak": {
"day_count": 0,
"bonus_percentage": 0,
"day_count_threshold": 0,
"required_daily_minutes": 0,
"completed_today": true,
"minutes_until_complete": 0,
"fails_in_minutes": 0
}
}GetUserProfileWatchtimeStreakobject
day_countintegerrequiredCurrent streak length in completed days (0 when there is no active streak).
bonus_percentageintegerrequiredReward bonus percent applied once the streak reaches the threshold.
day_count_thresholdintegerrequiredCompleted days required before the bonus activates.
required_daily_minutesintegerrequiredMinutes the user must watch each day to complete the day and keep the streak alive. Taken from the active streak's snapshot, or the live config default when no active streak exists.
completed_todaybooleanrequiredWhether the user has already completed today's watch requirement.
minutes_until_completeinteger | nullrequiredMinutes left to watch today to advance the streak. Null if completed today or no active streak exists.
fails_in_minutesinteger | nullrequiredMinutes until the streak fails if no further day is completed. Null if completed today or no active streak exists.
{
"day_count": 0,
"bonus_percentage": 0,
"day_count_threshold": 0,
"required_daily_minutes": 0,
"completed_today": true,
"minutes_until_complete": 0,
"fails_in_minutes": 0
}ListUserVideosResponseobject
itemsarray of Videorequired
idstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredfriend_likesarray of VideoFriendLikerequired
The requesting user's friends who liked this video, most recently liked first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
liked_atstring · date-timerequiredWhen the friend liked the video.
next_cursorstring | nullrequiredCursor for the next page (RFC3339Nano timestamp), null if no more items.
{
"items": [
{
"id": "string",
"creator_tag": "string",
"creator_name": "string",
"caption": "string",
"hls_url": "string",
"uploaded_at": "2026-08-09T12:00:00Z",
"liked_at": "2026-08-09T12:00:00Z",
"like_count": 0,
"view_count": 0,
"cta": {
"text": "string",
"url": "string"
},
"friend_likes": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"liked_at": "2026-08-09T12:00:00Z"
}
]
}
],
"next_cursor": "string"
}ListUserCreatorsResponseobject
itemsarray of Creatorrequired
tagstringrequiredThe creator's unique tag (username / public identifier).
namestringrequiredThe creator's display name; falls back to the tag when unset.
biostringrequiredpicture_urlstring | nullrequiredProfile picture URL; null when the creator has none set.
picture_stylestringrequiredHow the client should render the profile picture — "circle" (round avatar mask) or "cover" (full-bleed image, no mask).
circlecover
followed_atstring · date-time | nullrequiredTimestamp when the requesting user followed this creator; null when not followed.
video_countinteger · int64requiredfollowers_countinteger · int64requiredlinksarray of CreatorLinkrequired
textstringrequiredurlstringrequired{
"items": [
{
"tag": "string",
"name": "string",
"bio": "string",
"picture_url": "string",
"picture_style": "circle",
"followed_at": "2026-08-09T12:00:00Z",
"video_count": 0,
"followers_count": 0,
"links": [
{
"text": "string",
"url": "string"
}
]
}
]
}FollowCreatorRequestobject
actionstringrequiredfollowunfollow
{
"action": "follow"
}ListUserGamesResponseobject
gamesarray of Gamerequired
idstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
eventsarray of GameEventrequired
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredthreshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredmissionsarray of GameMissionrequired
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringstatusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
highscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
stateGameStaterequired
friend_highscoresarray of GameFriendHighscorerequired
The requesting user's friends who have played this game, with each friend's highscore, best first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
highscoreintegerrequiredThe friend's best result for this game (highest level for level games, highest score for highscore games).
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
{
"games": [
{
"id": "string",
"name": "string",
"icon_url": "string",
"banner_image_url": "string",
"card_image_url": "string",
"category": "arcade",
"game_url": "string",
"type": "level",
"version": 0,
"play_count": 0,
"is_in_endgame": true,
"events": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"sort_order": 0,
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"threshold_type": "level",
"blocked_by": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"marks_endgame": true,
"completed_at": "2026-08-09T12:00:00Z"
}
],
"missions": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"status": "not_started",
"joinable_until": "2026-08-09T12:00:00Z",
"minutes_to_complete": 0,
"goals": [
{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}
]
}
],
"highscore": 0,
"last_played_at": "2026-08-09T12:00:00Z",
"discovered_at": "2026-08-09T12:00:00Z",
"state": {
"key": {
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}
},
"friend_highscores": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"highscore": 0
}
],
"rating_count": 0,
"rating_avg": 0,
"user_rating": 0,
"section": "test"
}
]
}Showing the icon variant.
ListUserComicsResponseobject
itemsarray of Comicrequired
Each item only contains the next part the user has not ready yet or the last part of the comic.
idstringrequiredtitlestringrequireddescriptionstringrequiredcover_urlstringrequiredparts_countintegerrequiredThe total number of parts in the comic.
read_countinteger · int64requiredTotal number of finished part-reads of this comic across all users.
rating_countinteger · int64requiredTotal number of 1-5 star ratings across all of this comic's parts. Reported as 0 (together with rating_avg) until the comic has collected at least 5 part ratings in total.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0) across all of this comic's part ratings, truncated to one decimal place. Reported as 0 until the comic has collected at least 5 part ratings (see rating_count).
read_time_avgnumber · doublerequiredSum of the per-part median read times, in seconds (reads over one hour are excluded as outliers). 0 when none of the comic's parts have been read.
partsarray of ComicPartrequired
Depending on the request, this may contain all parts or only the next part the user has not read yet.
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
friend_reading_progressarray of ComicFriendReadingProgressrequired
The requesting user's friends who have read at least one part of this comic, furthest read first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
last_read_part_indexintegerrequiredThe highest part index the friend has read in this comic.
{
"items": [
{
"id": "string",
"title": "string",
"description": "string",
"cover_url": "string",
"parts_count": 0,
"read_count": 0,
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0,
"parts": [
{
"index": 0,
"version": "string",
"title": "string",
"description": "string",
"unlocked": true,
"finished_reading_at": "2026-08-09T12:00:00Z",
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"cover_url": "string",
"music_url": "string",
"pages": [
{
"page_type": "page",
"index": 0,
"video_url": "string"
},
{
"page_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}
],
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0
}
],
"friend_reading_progress": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"last_read_part_index": 0
}
]
}
]
}Showing all 2 variants of the union.
ReportVideoRequestobject
reasonstringrequiredsexual_contentviolent_or_repulsive_contenthateful_or_abusive_contentharassment_or_bullyingharmful_or_dangerous_actssuicide_self_harm_or_eating_disorders+5 more
misinformationchild_abusepromotes_terrorismspam_or_misleadinglegal_issue
{
"reason": "sexual_content"
}ListCreatorVideosResponseobject
itemsarray of Videorequired
idstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredfriend_likesarray of VideoFriendLikerequired
The requesting user's friends who liked this video, most recently liked first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
liked_atstring · date-timerequiredWhen the friend liked the video.
next_cursorstring | nullrequiredThe last video's id (UUID), used as the next page's cursor; null if no more items.
{
"items": [
{
"id": "string",
"creator_tag": "string",
"creator_name": "string",
"caption": "string",
"hls_url": "string",
"uploaded_at": "2026-08-09T12:00:00Z",
"liked_at": "2026-08-09T12:00:00Z",
"like_count": 0,
"view_count": 0,
"cta": {
"text": "string",
"url": "string"
},
"friend_likes": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"liked_at": "2026-08-09T12:00:00Z"
}
]
}
],
"next_cursor": "string"
}ListGamesResponseobject
itemsarray of Gamerequired
idstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
eventsarray of GameEventrequired
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredthreshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredmissionsarray of GameMissionrequired
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringstatusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
highscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
stateGameStaterequired
friend_highscoresarray of GameFriendHighscorerequired
The requesting user's friends who have played this game, with each friend's highscore, best first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
highscoreintegerrequiredThe friend's best result for this game (highest level for level games, highest score for highscore games).
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
{
"items": [
{
"id": "string",
"name": "string",
"icon_url": "string",
"banner_image_url": "string",
"card_image_url": "string",
"category": "arcade",
"game_url": "string",
"type": "level",
"version": 0,
"play_count": 0,
"is_in_endgame": true,
"events": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"sort_order": 0,
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"threshold_type": "level",
"blocked_by": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"marks_endgame": true,
"completed_at": "2026-08-09T12:00:00Z"
}
],
"missions": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"status": "not_started",
"joinable_until": "2026-08-09T12:00:00Z",
"minutes_to_complete": 0,
"goals": [
{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}
]
}
],
"highscore": 0,
"last_played_at": "2026-08-09T12:00:00Z",
"discovered_at": "2026-08-09T12:00:00Z",
"state": {
"key": {
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}
},
"friend_highscores": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"highscore": 0
}
],
"rating_count": 0,
"rating_avg": 0,
"user_rating": 0,
"section": "test"
}
]
}Showing the icon variant.
PostGamePlayRequestobject
scoreinteger | nullrequiredLevel reached (level games) or score achieved (highscore games). Null on game over.
playtime_secondsintegerrequiredWhole seconds the client played since the previous submission, so a continued round's submissions each carry their own slice rather than the round's total.
idempotency_keystring · uuidprevious_play_idstring · uuidThe play_id of the submission this one continues, when the client is resuming a round rather than starting one. It must be the caller's most recent play of this game — a shop transaction in between does not end a round — and a round may be continued at most 5 times. Omit to start a new round.
state_changemap<string, PostGamePlayStateDelta>
Per-value state changes keyed by value name (may be empty or omitted). Each name must be configured on the game and each operation must be one the value's type supports; anything else returns 400 invalid_state_change. The changes are applied to the user's running state snapshot for this game, which the response returns as state.
«key»PostGamePlayStateDelta
incrementinteger · int64Amount to add to a counter (non-negative) or gauge value this play. A gauge takes either sign, so a negative increment is how it moves down.
change_stringstringThe new value of a string value, overriding whatever was stored. Must match the value's configured pattern.
change_booleanbooleanThe new value of a boolean value, overriding whatever was stored.
change_numbernumber · doubleThe new value of a number value, overriding whatever was stored.
set_addarray of stringElements to add to a set value. Each must be one of the value's configured elements.
set_removearray of stringElements to drop from a set value. Each must be one of the value's configured elements and may not also be added.
list_addarray of anyItems to append to a list value, each shaped by the value's configured item schema.
list_removearray of integerPositions to drop from a list value, as indices into the list as it was before this play.
list_replacearray of PostGamePlayStateReplace
Items to overwrite in a list value.
indexintegerrequiredPosition in the list as it was before this play. Must exist.
valueany | nullrequiredThe item to store at that position, shaped by the value's configured item schema.
placementstringWhere the play occurred: inside the video feed or the dedicated games tab. Defaults to feed when omitted.
feedgames_tab
{
"score": 0,
"playtime_seconds": 0,
"idempotency_key": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"previous_play_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"state_change": {
"key": {
"increment": 0,
"change_string": "string",
"change_boolean": true,
"change_number": 0,
"set_add": [
"string"
],
"set_remove": [
"string"
],
"list_add": [],
"list_remove": [
0
],
"list_replace": [
{
"index": 0,
"value": null
}
]
}
},
"placement": "feed"
}PostGamePlayStateDeltaobject
The operations one play applies to a single state value. Every field is optional and each one belongs to a single value type, so only the operations of the value's configured type may be set - anything else returns 400 invalid_state_change:
| type | operations |
|---|---|
| counter | increment (non-negative) |
| gauge | increment (either sign) |
| string | change_string (must match the configured pattern) |
| boolean | change_boolean |
| number | change_number |
| set | set_add, set_remove (configured elements) |
| list | list_add, list_remove (indices), list_replace |
A value may carry several operations at once. List operations are applied in a fixed order - list_replace, then list_remove, then list_add - and every index refers to the list as it was before this play, so indices do not shift underneath each other.
A play that breaks a bound is rejected whole: taking a list past its max_items, taking the game's whole state for this user past its size limit, or overflowing a counter's or gauge's total - a signed 64-bit integer - returns 400 invalid_state_change rather than applying the part that fits. Short of that overflow a counter's total and a gauge's value are unbounded. The state as a whole is bounded even though each value is bounded on its own, since nothing about a single value's limits bounds their sum, and every play stores the whole state.
incrementinteger · int64Amount to add to a counter (non-negative) or gauge value this play. A gauge takes either sign, so a negative increment is how it moves down.
change_stringstringThe new value of a string value, overriding whatever was stored. Must match the value's configured pattern.
change_booleanbooleanThe new value of a boolean value, overriding whatever was stored.
change_numbernumber · doubleThe new value of a number value, overriding whatever was stored.
set_addarray of stringElements to add to a set value. Each must be one of the value's configured elements.
set_removearray of stringElements to drop from a set value. Each must be one of the value's configured elements and may not also be added.
list_addarray of anyItems to append to a list value, each shaped by the value's configured item schema.
list_removearray of integerPositions to drop from a list value, as indices into the list as it was before this play.
list_replacearray of PostGamePlayStateReplace
Items to overwrite in a list value.
indexintegerrequiredPosition in the list as it was before this play. Must exist.
valueany | nullrequiredThe item to store at that position, shaped by the value's configured item schema.
{
"increment": 0,
"change_string": "string",
"change_boolean": true,
"change_number": 0,
"set_add": [
"string"
],
"set_remove": [
"string"
],
"list_add": [],
"list_remove": [
0
],
"list_replace": [
{
"index": 0,
"value": null
}
]
}The operations one play applies to a single state value. Every field is optional and each one belongs to a single value type, so only the operations of the value's configured type may be set - anything else returns 400 invalid_state_change:
| type | operations |
|---|---|
| counter | increment (non-negative) |
| gauge | increment (either sign) |
| string | change_string (must match the configured pattern) |
| boolean | change_boolean |
| number | change_number |
| set | set_add, set_remove (configured elements) |
| list | list_add, list_remove (indices), list_replace |
A value may carry several operations at once. List operations are applied in a fixed order - list_replace, then list_remove, then list_add - and every index refers to the list as it was before this play, so indices do not shift underneath each other.
A play that breaks a bound is rejected whole: taking a list past its max_items, taking the game's whole state for this user past its size limit, or overflowing a counter's or gauge's total - a signed 64-bit integer - returns 400 invalid_state_change rather than applying the part that fits. Short of that overflow a counter's total and a gauge's value are unbounded. The state as a whole is bounded even though each value is bounded on its own, since nothing about a single value's limits bounds their sum, and every play stores the whole state.
PostGamePlayStateReplaceobject
indexintegerrequiredPosition in the list as it was before this play. Must exist.
valueany | nullrequiredThe item to store at that position, shaped by the value's configured item schema.
{
"index": 0,
"value": null
}PostGamePlayResponseobject
play_idstring · uuid | nullrequiredHandle of the submission just recorded, to send back as previous_play_id when continuing this round. Null when the play was dropped (duplicate submission, rate limit): nothing was recorded, so there is nothing to continue.
stateGameStaterequired
The user's game state after this play, with every configured value present. Returned unchanged when the play was dropped (duplicate submission, rate limit), so the client can always reconcile against it.
«key»GameStateValue
totalinteger · int64A counter's or gauge's current total. Both only ever move by whole increments, so this is a whole number - exact across the full int64 range, of which a client reading it into a double can represent up to 2^53.
numbernumber · doubleA number value's current value.
stringstringA string value's current value.
booleanbooleanA boolean value's current value.
setarray of stringA set value's current elements, sorted. Always present (and empty when nothing is held) for set values.
listarray of anyA list value's current items in order, each shaped by the item schema configured for the value. Always present (and empty when nothing is held) for list values.
earned_local_currencyReward | nullrequired
Local currency earned this request, or null if nothing was earned.
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
completed_eventsarray of GameEventrequired
Events completed this request.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
threshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredcompleted_missionsarray of GameMissionrequired
Missions completed this request.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
statusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
goalsarray of GameMissionGoalrequired
translationsmap<string, string>required
«key»stringvaluenumber · doublerequiredThe user's current progress toward the goal.
thresholdnumber · doublerequiredThe value at which the goal completes.
completedbooleanrequiredadAd | nullrequired
An ad to show, served on a fixed cadence; null otherwise.
slot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
{
"play_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"state": {
"key": {
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}
},
"earned_local_currency": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"completed_events": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"sort_order": 0,
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"threshold_type": "level",
"blocked_by": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"marks_endgame": true,
"completed_at": "2026-08-09T12:00:00Z"
}
],
"completed_missions": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"status": "not_started",
"joinable_until": "2026-08-09T12:00:00Z",
"minutes_to_complete": 0,
"goals": [
{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}
]
}
],
"ad": {
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}
}Showing the icon variant.
PostGameShopRequestobject
state_changemap<string, PostGamePlayStateDelta>required
Per-value state changes keyed by value name, in the same form the play endpoint takes and held to the same per-value bounds. These are the values the purchase moved.
«key»PostGamePlayStateDelta
incrementinteger · int64Amount to add to a counter (non-negative) or gauge value this play. A gauge takes either sign, so a negative increment is how it moves down.
change_stringstringThe new value of a string value, overriding whatever was stored. Must match the value's configured pattern.
change_booleanbooleanThe new value of a boolean value, overriding whatever was stored.
change_numbernumber · doubleThe new value of a number value, overriding whatever was stored.
set_addarray of stringElements to add to a set value. Each must be one of the value's configured elements.
set_removearray of stringElements to drop from a set value. Each must be one of the value's configured elements and may not also be added.
list_addarray of anyItems to append to a list value, each shaped by the value's configured item schema.
list_removearray of integerPositions to drop from a list value, as indices into the list as it was before this play.
list_replacearray of PostGamePlayStateReplace
Items to overwrite in a list value.
indexintegerrequiredPosition in the list as it was before this play. Must exist.
valueany | nullrequiredThe item to store at that position, shaped by the value's configured item schema.
idempotency_keystring · uuidplacementstringWhere the game was running when the transaction happened: inside the video feed or the dedicated games tab. Defaults to feed when omitted.
feedgames_tab
{
"state_change": {
"key": {
"increment": 0,
"change_string": "string",
"change_boolean": true,
"change_number": 0,
"set_add": [
"string"
],
"set_remove": [
"string"
],
"list_add": [],
"list_remove": [
0
],
"list_replace": [
{
"index": 0,
"value": null
}
]
}
},
"idempotency_key": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"placement": "feed"
}PostGameShopResponseobject
stateGameStaterequired
The user's game state after the transaction, with every configured value present.
«key»GameStateValue
totalinteger · int64A counter's or gauge's current total. Both only ever move by whole increments, so this is a whole number - exact across the full int64 range, of which a client reading it into a double can represent up to 2^53.
numbernumber · doubleA number value's current value.
stringstringA string value's current value.
booleanbooleanA boolean value's current value.
setarray of stringA set value's current elements, sorted. Always present (and empty when nothing is held) for set values.
listarray of anyA list value's current items in order, each shaped by the item schema configured for the value. Always present (and empty when nothing is held) for list values.
earned_local_currencyReward | nullrequired
Local currency earned this request, or null if nothing was earned.
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
completed_eventsarray of GameEventrequired
Events the transaction completed.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
threshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredcompleted_missionsarray of GameMissionrequired
Missions the transaction completed.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
statusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
goalsarray of GameMissionGoalrequired
translationsmap<string, string>required
«key»stringvaluenumber · doublerequiredThe user's current progress toward the goal.
thresholdnumber · doublerequiredThe value at which the goal completes.
completedbooleanrequired{
"state": {
"key": {
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}
},
"earned_local_currency": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"completed_events": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"sort_order": 0,
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"threshold_type": "level",
"blocked_by": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"marks_endgame": true,
"completed_at": "2026-08-09T12:00:00Z"
}
],
"completed_missions": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"status": "not_started",
"joinable_until": "2026-08-09T12:00:00Z",
"minutes_to_complete": 0,
"goals": [
{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}
]
}
]
}Showing the icon variant.
GetGameLeaderboardResponseobject
ranksarray of GameLeaderboardRankrequired
The top 50 users for the game, ordered by rank ascending. Users without a username are left out - except the requesting user themselves, who is always listed at their own position when they have one, so an unnamed user sees their rank without appearing on anyone else's board.
rankinteger | nullrequired1-based position in the leaderboard; null in user_rank when the user is not in the top 50.
usernamestringrequiredpicture_urlstringrequiredscoreintegerrequiredBest level (level games) or best score (highscore games); 0 if never played.
user_rankGameLeaderboardRankrequired
rankinteger | nullrequired1-based position in the leaderboard; null in user_rank when the user is not in the top 50.
usernamestringrequiredpicture_urlstringrequiredscoreintegerrequiredBest level (level games) or best score (highscore games); 0 if never played.
{
"ranks": [
{
"rank": 0,
"username": "string",
"picture_url": "string",
"score": 0
}
],
"user_rank": {
"rank": 0,
"username": "string",
"picture_url": "string",
"score": 0
}
}GameLeaderboardRankobject
rankinteger | nullrequired1-based position in the leaderboard; null in user_rank when the user is not in the top 50.
usernamestringrequiredpicture_urlstringrequiredscoreintegerrequiredBest level (level games) or best score (highscore games); 0 if never played.
{
"rank": 0,
"username": "string",
"picture_url": "string",
"score": 0
}MarkComicPartReadRequestobject
pagesarray of objectrequired
Per page user metrics.
indexintegerrequiredThe index of the page.
read_secondsnumber · doublerequiredThe number of seconds the user read the page.
{
"pages": [
{
"index": 0,
"read_seconds": 0
}
]
}MarkComicPartReadResponseobject
next_partobject | nullrequired
The next part of the comic to read, or null if there is no next part. Carries part metadata only — its pages are null; fetch them from GET /v1/comics/{comic_id}/parts/{part_index}.
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
rewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
pagesarray of ComicPartPagesItem | nullrequired
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
page_type = "page" ComicPartPage
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequiredpage_type = "ad" ComicPartPageAd
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
earned_local_currencyReward | nullrequired
Local currency earned this request, or null if nothing was earned.
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
{
"next_part": {
"index": 0,
"version": "string",
"title": "string",
"description": "string",
"unlocked": true,
"finished_reading_at": "2026-08-09T12:00:00Z",
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"cover_url": "string",
"music_url": "string",
"pages": [
{
"page_type": "page",
"index": 0,
"video_url": "string"
},
{
"page_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}
],
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0
},
"earned_local_currency": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
}
}Showing all 2 variants of the union.
RateGameRequestobject
ratingintegerrequiredThe rating in whole stars, from 1 to 5. Values outside this range are rejected with invalid_rating.
{
"rating": 1
}RateComicPartRequestobject
ratingintegerrequiredThe rating in whole stars, from 1 to 5. Values outside this range are rejected with invalid_rating.
{
"rating": 1
}CreateAdRequestobject
typestringrequiredofferexternal
external_sub_typestring | nullSub-type for external ads; null or omitted otherwise.
nativeinterstitialrewarded
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
placementstringrequiredThe placement this ad belongs to.
feedgame
media_typestring | nullThe type of media the slot references. Only game media is client-referenceable (feed and comic ads are server-managed). Null or omitted when no specific media is referenced.
media_refstring | nullThe referenced media's public id: the game's id/slug (e.g. arrow-escape). Stored as-is. Null or omitted when no specific media is referenced.
{
"type": "offer",
"external_sub_type": "native",
"lock_seconds": 0,
"placement": "feed",
"media_type": "game",
"media_ref": "string"
}FillClientAdRequestobject
client_dataAdClientDatarequired
ad_platformstringad_sourcestringad_formatstringad_unit_namestringcurrencystringISO 4217 currency code for the bid.
bidstringBid amount as a decimal string (e.g. "1.25").
{
"client_data": {
"ad_platform": "string",
"ad_source": "string",
"ad_format": "string",
"ad_unit_name": "string",
"currency": "str",
"bid": "string"
}
}AdClientDataobject
Client-reported ad attribution. All fields are optional; string fields are truncated and the bid is capped server-side.
ad_platformstringad_sourcestringad_formatstringad_unit_namestringcurrencystringISO 4217 currency code for the bid.
bidstringBid amount as a decimal string (e.g. "1.25").
{
"ad_platform": "string",
"ad_source": "string",
"ad_format": "string",
"ad_unit_name": "string",
"currency": "str",
"bid": "string"
}Client-reported ad attribution. All fields are optional; string fields are truncated and the bid is capped server-side.
RewardDisplayIconobject
Render the amount with the icon at icon_url on the given side of it.
{
"type": "icon",
"icon_url": "string",
"position": "left"
}RewardDisplayPlainobject
Render the amount with symbol on the given side of it, e.g. "$1.50".
{
"type": "plain",
"symbol": "string",
"position": "left"
}ComicPartPageobject
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequired{
"page_type": "page",
"index": 0,
"video_url": "string"
}ComicPartPageAdallOf
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
{
"page_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}Videoobject
idstringrequiredcreatorstringrequireddeprecatedDeprecated; use creator_name. Holds the same value as creator_name.
creator_tagstringrequiredThe creator's tag (unique username / public identifier).
creator_namestringrequiredThe creator's display name; falls back to the tag when unset.
captionstringrequiredhls_urlstringrequireduploaded_atstring · date-timerequiredliked_atstring · date-time | nullrequiredlike_countinteger · int64requiredview_countinteger · int64requiredNumber of times the video has been watched.
ctaobject | nullrequired
textstringrequiredurlstringrequiredfriend_likesarray of VideoFriendLikerequired
The requesting user's friends who liked this video, most recently liked first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
liked_atstring · date-timerequiredWhen the friend liked the video.
{
"id": "string",
"creator_tag": "string",
"creator_name": "string",
"caption": "string",
"hls_url": "string",
"uploaded_at": "2026-08-09T12:00:00Z",
"liked_at": "2026-08-09T12:00:00Z",
"like_count": 0,
"view_count": 0,
"cta": {
"text": "string",
"url": "string"
},
"friend_likes": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"liked_at": "2026-08-09T12:00:00Z"
}
]
}Creatorobject
tagstringrequiredThe creator's unique tag (username / public identifier).
namestringrequiredThe creator's display name; falls back to the tag when unset.
biostringrequiredpicture_urlstring | nullrequiredProfile picture URL; null when the creator has none set.
picture_stylestringrequiredHow the client should render the profile picture — "circle" (round avatar mask) or "cover" (full-bleed image, no mask).
circlecover
followed_atstring · date-time | nullrequiredTimestamp when the requesting user followed this creator; null when not followed.
video_countinteger · int64requiredfollowers_countinteger · int64requiredlinksarray of CreatorLinkrequired
textstringrequiredurlstringrequired{
"tag": "string",
"name": "string",
"bio": "string",
"picture_url": "string",
"picture_style": "circle",
"followed_at": "2026-08-09T12:00:00Z",
"video_count": 0,
"followers_count": 0,
"links": [
{
"text": "string",
"url": "string"
}
]
}Gameobject
idstringrequiredThe game slug (e.g. "arrow-escape").
namestringrequiredicon_urlstringrequiredbanner_image_urlstringrequiredcard_image_urlstringrequiredgame_urlstringrequiredversionintegerrequiredThe event-set version the user is on: the version of the user's completed events, or the newest version if they have not completed any event for this game yet.
play_countinteger · int64requiredTotal number of recorded plays of this game across all users.
is_in_endgamebooleanrequiredWhether the user has reached the endgame for this game: completed the event marked as the endgame in the version they are on. False when that version has no endgame event. Missions can only be joined once this is true.
eventsarray of GameEventrequired
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
threshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequiredmissionsarray of GameMissionrequired
The user's started missions (ongoing, and completed until they reset) plus the missions they could start by playing now.
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
statusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
goalsarray of GameMissionGoalrequired
translationsmap<string, string>required
«key»stringvaluenumber · doublerequiredThe user's current progress toward the goal.
thresholdnumber · doublerequiredThe value at which the goal completes.
completedbooleanrequiredhighscoreinteger | nullrequiredThe user's best result for this game (highest level for level games, highest score for highscore games). Null when the user has not played this game yet or has no score yet.
last_played_atstring · date-time | nullrequiredTime of the user's most recent play, or null if never played.
discovered_atstring · date-time | nullrequiredTime of the user's first play of this game, or null if never played.
stateGameStaterequired
«key»GameStateValue
totalinteger · int64A counter's or gauge's current total. Both only ever move by whole increments, so this is a whole number - exact across the full int64 range, of which a client reading it into a double can represent up to 2^53.
numbernumber · doubleA number value's current value.
stringstringA string value's current value.
booleanbooleanA boolean value's current value.
setarray of stringA set value's current elements, sorted. Always present (and empty when nothing is held) for set values.
listarray of anyA list value's current items in order, each shaped by the item schema configured for the value. Always present (and empty when nothing is held) for list values.
friend_highscoresarray of GameFriendHighscorerequired
The requesting user's friends who have played this game, with each friend's highscore, best first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
highscoreintegerrequiredThe friend's best result for this game (highest level for level games, highest score for highscore games).
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this game. Reported as 0 (together with rating_avg) until the game has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the game has collected at least 5 ratings (see rating_count).
user_ratinginteger | nullrequiredThe 1-5 star rating the requesting user submitted for this game, or null if they have not rated it. Unlike rating_count and rating_avg this is never hidden, and it never changes once set — a rating is immutable. Always null where there is no authenticated user, such as the public games catalog.
{
"id": "string",
"name": "string",
"icon_url": "string",
"banner_image_url": "string",
"card_image_url": "string",
"category": "arcade",
"game_url": "string",
"type": "level",
"version": 0,
"play_count": 0,
"is_in_endgame": true,
"events": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"sort_order": 0,
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"threshold_type": "level",
"blocked_by": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"marks_endgame": true,
"completed_at": "2026-08-09T12:00:00Z"
}
],
"missions": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"status": "not_started",
"joinable_until": "2026-08-09T12:00:00Z",
"minutes_to_complete": 0,
"goals": [
{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}
]
}
],
"highscore": 0,
"last_played_at": "2026-08-09T12:00:00Z",
"discovered_at": "2026-08-09T12:00:00Z",
"state": {
"key": {
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}
},
"friend_highscores": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"highscore": 0
}
],
"rating_count": 0,
"rating_avg": 0,
"user_rating": 0,
"section": "test"
}Showing the icon variant.
Comicobject
idstringrequiredtitlestringrequireddescriptionstringrequiredcover_urlstringrequiredparts_countintegerrequiredThe total number of parts in the comic.
read_countinteger · int64requiredTotal number of finished part-reads of this comic across all users.
rating_countinteger · int64requiredTotal number of 1-5 star ratings across all of this comic's parts. Reported as 0 (together with rating_avg) until the comic has collected at least 5 part ratings in total.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0) across all of this comic's part ratings, truncated to one decimal place. Reported as 0 until the comic has collected at least 5 part ratings (see rating_count).
read_time_avgnumber · doublerequiredSum of the per-part median read times, in seconds (reads over one hour are excluded as outliers). 0 when none of the comic's parts have been read.
partsarray of ComicPartrequired
Depending on the request, this may contain all parts or only the next part the user has not read yet.
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
rewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
pagesarray of ComicPartPagesItem | nullrequired
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
page_type = "page" ComicPartPage
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequiredpage_type = "ad" ComicPartPageAd
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
friend_reading_progressarray of ComicFriendReadingProgressrequired
The requesting user's friends who have read at least one part of this comic, furthest read first.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
last_read_part_indexintegerrequiredThe highest part index the friend has read in this comic.
{
"id": "string",
"title": "string",
"description": "string",
"cover_url": "string",
"parts_count": 0,
"read_count": 0,
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0,
"parts": [
{
"index": 0,
"version": "string",
"title": "string",
"description": "string",
"unlocked": true,
"finished_reading_at": "2026-08-09T12:00:00Z",
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"cover_url": "string",
"music_url": "string",
"pages": [
{
"page_type": "page",
"index": 0,
"video_url": "string"
},
{
"page_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}
],
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0
}
],
"friend_reading_progress": [
{
"uid": "string",
"username": "string",
"picture_url": "string",
"last_read_part_index": 0
}
]
}Showing all 2 variants of the union.
ComicPartobject
indexintegerrequiredThe index of the part in the comic.
versionstringrequiredThe version of the part.
titlestringrequireddescriptionstringrequiredunlockedbooleanrequiredWhether the part is unlocked (already read, or the single next readable part). When false, music_url and pages are null. Pages are only ever populated by GET /v1/comics/{comic_id}/parts/{part_index}, so an unlocked part still has null pages in the list/detail/feed views.
finished_reading_atstring · date-time | nullrequiredThe timestamp the user finished reading the part.
rewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
cover_urlstringrequiredmusic_urlstring | nullrequiredThe URL of the music for the part. Null if the part is locked.
pagesarray of ComicPartPagesItem | nullrequired
The pages and ads of the part. Only populated by GET /v1/comics/{comic_id}/parts/{part_index} (the full part view); null in the list/detail/feed views and for locked parts.
page_type = "page" ComicPartPage
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequiredpage_type = "ad" ComicPartPageAd
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
rating_countinteger · int64requiredNumber of 1-5 star ratings submitted for this part. Reported as 0 (together with rating_avg) until the part has collected at least 5 ratings, so early, unrepresentative scores are hidden.
rating_avgnumber · doublerequiredAverage star rating (1.0-5.0), truncated to one decimal place. Reported as 0 until the part has collected at least 5 ratings (see rating_count).
read_time_avgnumber · doublerequiredMedian time, in seconds, users spent reading this part (reads over one hour are excluded as outliers). 0 when the part has not been read yet.
{
"index": 0,
"version": "string",
"title": "string",
"description": "string",
"unlocked": true,
"finished_reading_at": "2026-08-09T12:00:00Z",
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"cover_url": "string",
"music_url": "string",
"pages": [
{
"page_type": "page",
"index": 0,
"video_url": "string"
},
{
"page_type": "ad",
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}
],
"rating_count": 0,
"rating_avg": 0,
"read_time_avg": 0
}Showing all 2 variants of the union.
Adobject
slot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
{
"slot_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "offer",
"lock_seconds": 0,
"external_sub_type": "native"
}Rewardobject
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
{
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
}Showing the icon variant.
GameStatemap
The user's current game state keyed by value name: the latest snapshot, or every configured value at its zero state when the user has not played yet. Which field of each value is populated follows the value's configured type.
«key»GameStateValue
totalinteger · int64A counter's or gauge's current total. Both only ever move by whole increments, so this is a whole number - exact across the full int64 range, of which a client reading it into a double can represent up to 2^53.
numbernumber · doubleA number value's current value.
stringstringA string value's current value.
booleanbooleanA boolean value's current value.
setarray of stringA set value's current elements, sorted. Always present (and empty when nothing is held) for set values.
listarray of anyA list value's current items in order, each shaped by the item schema configured for the value. Always present (and empty when nothing is held) for list values.
{
"key": {
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}
}GameEventobject
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringsort_orderintegerrequiredrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
threshold_typestringrequiredlevelhighscoregames_playedcountergaugeset
blocked_bystring · uuid | nullrequiredpublic_id of the event that must be completed first, or null.
marks_endgamebooleanrequiredWhether completing this event marks the user as having reached the endgame. At most one event per version sets this.
completed_atstring · date-time | nullrequired{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"sort_order": 0,
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"threshold_type": "level",
"blocked_by": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"marks_endgame": true,
"completed_at": "2026-08-09T12:00:00Z"
}Showing the icon variant.
GameMissionobject
idstring · uuidrequiredtranslationsmap<string, string>required
«key»stringrewardRewardrequired
totalstringrequiredtotal = bonus + base
bonusstringrequiredbasestringrequireddisplayoneOf · 2 variantsrequired
How the client should render the amounts, as configured for the user's currency. Falls back to a leading "$" where the app configures no rendering for that currency, and wherever there is no user to read a currency from, such as the public games catalog.
type = "icon" RewardDisplayIcon
type = "plain" RewardDisplayPlain
statusstringrequirednot_startedongoingcompleted
joinable_untilstring · date-time | nullrequiredUntil when the mission can be started, or null when unbounded.
minutes_to_completeintegerrequiredMinutes the user has to complete the mission: the full cadence window (1440 for daily) before starting, the remainder until the mission resets once started.
goalsarray of GameMissionGoalrequired
translationsmap<string, string>required
«key»stringvaluenumber · doublerequiredThe user's current progress toward the goal.
thresholdnumber · doublerequiredThe value at which the goal completes.
completedbooleanrequired{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"translations": {
"key": "string"
},
"reward": {
"total": "string",
"bonus": "string",
"base": "string",
"display": {
"type": "icon",
"icon_url": "string",
"position": "left"
}
},
"status": "not_started",
"joinable_until": "2026-08-09T12:00:00Z",
"minutes_to_complete": 0,
"goals": [
{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}
]
}Showing the icon variant.
Errorobject
errorstringcodestringMachine-readable error code; omitted when the error has none.
{
"error": "string",
"code": "string"
}VideoFriendLikeallOf
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
liked_atstring · date-timerequiredWhen the friend liked the video.
{
"uid": "string",
"username": "string",
"picture_url": "string",
"liked_at": "2026-08-09T12:00:00Z"
}Friendobject
A compact projection of a friend user.
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
{
"uid": "string",
"username": "string",
"picture_url": "string"
}CreatorLinkobject
textstringrequiredurlstringrequired{
"text": "string",
"url": "string"
}RewardDisplayPositionenum
Which side of the amount the icon or symbol goes on.
leftright
"left"GameCategoryenum
Game category slug.
arcadeboard-cardcasualentertainmentpuzzlerole-playingstrategyother
"arcade"GameTypeenum
levelhighscore
"level"GameFriendHighscoreallOf
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
highscoreintegerrequiredThe friend's best result for this game (highest level for level games, highest score for highscore games).
{
"uid": "string",
"username": "string",
"picture_url": "string",
"highscore": 0
}GameSectionenum
Which block of the games tab a game belongs to, for rendering the section headers, in the order the sections appear: test holds the test-user-only games and reaches test users only, continue_playing the games the user is part-way through, discover the rest. Responses that rank nothing for a specific user — a single game, the public catalog, a game injected into the feed — report discover.
testcontinue_playingdiscover
"test"GameMissionGoalobject
translationsmap<string, string>required
«key»stringvaluenumber · doublerequiredThe user's current progress toward the goal.
thresholdnumber · doublerequiredThe value at which the goal completes.
completedbooleanrequired{
"translations": {
"key": "string"
},
"value": 0,
"threshold": 0,
"completed": true
}GameStateValueobject
One state value. Exactly one field carries the value, chosen by the type it is configured as: total for counter and gauge values, number for number values, string/boolean/set/list for the others. The fields that do not apply are omitted.
totalinteger · int64A counter's or gauge's current total. Both only ever move by whole increments, so this is a whole number - exact across the full int64 range, of which a client reading it into a double can represent up to 2^53.
numbernumber · doubleA number value's current value.
stringstringA string value's current value.
booleanbooleanA boolean value's current value.
setarray of stringA set value's current elements, sorted. Always present (and empty when nothing is held) for set values.
listarray of anyA list value's current items in order, each shaped by the item schema configured for the value. Always present (and empty when nothing is held) for list values.
{
"total": 0,
"number": 0,
"string": "string",
"boolean": true,
"set": [
"string"
],
"list": []
}One state value. Exactly one field carries the value, chosen by the type it is configured as: total for counter and gauge values, number for number values, string/boolean/set/list for the others. The fields that do not apply are omitted.
ComicFriendReadingProgressallOf
uidstringrequiredThe friend's external user id (app-scoped public identifier).
usernamestring | nullrequiredThe friend's username; null when unset.
picture_urlstring | nullrequiredThe friend's profile picture URL; null when unset.
last_read_part_indexintegerrequiredThe highest part index the friend has read in this comic.
{
"uid": "string",
"username": "string",
"picture_url": "string",
"last_read_part_index": 0
}ComicPartPagesItemoneOf · 2
page_type = "page" ComicPartPage
page_typestringrequiredindexintegerrequiredThe index of the page in the part.
video_urlstringrequiredpage_type = "ad" ComicPartPageAd
page_typestringrequiredslot_idstring · uuidrequiredThe ad slot's id. Use it to fill the slot via PATCH/v1/ads/{id}.
typestringrequiredofferexternal
lock_secondsintegerrequiredHow long the ad is locked before it can be skipped.
external_sub_typestring | nullrequiredSub-type of an external ad; null for non-external ads.
nativeinterstitialrewarded
{
"page_type": "page",
"index": 0,
"video_url": "string"
}Showing the page variant.