Skip to content
Micup API

Table games

A ranked table game season is one Istanbul calendar month. Two hours after a season ends, a background job freezes the first 100 places of each ranked game’s leaderboard and writes one reward candidate per place. A second job reads each candidate’s games of that season and either marks the candidate ineligible or puts it up for review. Nothing is given until staff approve a candidate with the routes on this page. These routes also set the rewards of the five tiers, read the table games of one account, and reset, exclude and reinstate a player. Every route on this page requires table_game:manage and records an Admin audit entry, reads included.

A value the server cannot accept returns 400 INVALID_FORM_BODY, with one element in errors for each refused field and an English message.

ValueDescription
rank1First place
rank2Second place
rank3Third place
top10Places 4 through 10
top100Places 11 through 100

A place that is not taken, or whose candidate is refused, is not passed on: the places stay as they were frozen.

The type field decides the other field.

FieldTypeDescription
typestringpremium_days, cosmetic, badge or offsite
days1integerThe Micup Plus days granted (1-365)
item_id2snowflakeThe ID of an avatar decoration
badge_id3snowflakeThe ID of a badge
description4stringWhat staff hand over by hand (1-200 characters)

1 Present for premium_days

2 Present for cosmetic. The item must be an avatar decoration with owned availability that is not in the shop catalog and is not a Visionary reward

3 Present for badge. The badge must exist and must not be numbered

4 Present for offsite

FieldTypeDescription
rank1array[season reward object]The rewards of first place
rank2array[season reward object]The rewards of second place
rank3array[season reward object]The rewards of third place
top10array[season reward object]The rewards of places 4 through 10
top100array[season reward object]The rewards of places 11 through 100
showcase_titlestringThe showcase heading, trimmed and at most 80 characters; an empty string uses the client’s translated default
updated_at?ISO8601 timestampWhen the rewards were last saved, null before the first save
chance_rewards_enabledbooleanWhether okey and okey 101 candidates receive Micup Plus days

The rewards live in the instance configuration under the table_game_rewards_config key, and no public instance route returns them. Signed-in users read the reward showcase. The showcase heading and off-site reward descriptions are visible to those users. The feature_table_game_chance_rewards limit key sets chance_rewards_enabled. It is 0 by default, and while it is 0 a premium_days reward of an okey or okey 101 candidate is withheld.

ValueDescription
analyzingThe candidate’s games are being read
reviewThe candidate waits for a staff decision
ineligibleThe account was gone, banned or limited at close, met too few opponents, or is excluded from the season
approvedStaff approved the reward, and its delivery is queued
rejectedStaff refused the reward
deliveringThe reward is being given
deliveredEvery reward was given
pending_offsiteEvery reward was given except an off-site one, which staff hand over by hand
revokedStaff took the reward back after it was given
voidThe account was gone, banned, limited or excluded from the season when the reward was to be given

A candidate moves only along these steps:

ActionMoves
approveFrom review or rejected to approved
rejectFrom review or approved to rejected
mark_offsite_deliveredFrom pending_offsite to delivered
revokeFrom delivered or pending_offsite to revoked
reconsiderFrom ineligible to review, unless the candidate is flagged account_gone or account_banned
ValueDescription
account_goneThe account was deleted, self-deleted, marked as a spammer or scheduled for deletion at close
account_bannedThe account was banned at close
account_limitedThe account was limited at close
few_opponentsThe account met fewer than 10 different rated opponents in the season
closed_clusterHalf or more of at least 10 wins came against 3 opponents or fewer
one_way_flowThe account won 80% or more of at least 10 rated games against one opponent
flagged_matchesAt least 3 of the season’s games carry a match flag
flagged_opponentsOne of the 20 opponents beaten most is gone, banned, limited, or under a sanction of the last 400 days
history_truncatedThe season holds more games than the analysis reads, and only the newest were read
own_sanctionThe account itself has a sanction not lifted: an exclusion from this season and game, or one of the last 400 days

A flag only orders the review and keeps a candidate out of Approve unflagged candidates. The decision is the reviewer’s.

The analysis reads at most 20000 rated games of the candidate’s game and 100000 ranked games in all. A candidate flagged history_truncated and few_opponents goes to review, not ineligible, since the games not read may hold more opponents. An exclusion from the season and game makes a candidate ineligible whatever its other flags; any other sanction of its own, in any game, only flags it.

ValueDescription
chance_gameA Micup Plus reward of an okey or okey 101 candidate while chance rewards are off
item_unavailableThe avatar decoration no longer existed when the reward was given
badge_missingThe badge no longer existed when the reward was given
FieldTypeDescription
rewardseason reward objectThe reward as the tiers stood when the season closed
withheld?stringThe withheld reason of a reward that is not given, otherwise null
FieldTypeDescription
gamesintegerThe rated games of the season in this game
winsintegerThe games the account won
distinct_opponentsintegerThe different rated opponents the account met
top3_win_sharenumberThe share of wins taken from the 3 opponents beaten most (0-1)
one_wayarray[one way opponent object]The opponents behind a one_way_flow flag
flagged_matchesintegerThe games that carry a match flag
flagged_opponentsarray[snowflake]The opponents behind a flagged_opponents flag
truncatedbooleanWhether only the newest games were read
FieldTypeDescription
user_idsnowflakeThe ID of the opponent
gamesintegerThe rated games against the opponent
win_ratenumberThe share of those games the account won
FieldTypeDescription
seasonintegerThe season as YYYYMM
gamestringThe game kind
user_idsnowflakeThe ID of the account
user?partial user objectThe account, null when it no longer exists
rankintegerThe frozen place (1-100)
tierstringThe reward tier
scorenumberThe leaderboard score at close
leaguestringThe league at close
rrintegerThe rank rating at close, 0 below the legend league
statusstringThe candidate status
flagsarray[string]The candidate flags
signals?candidate signals objectThe summary of the season’s games, null before analysis
rewardsarray[stored reward object]The rewards of the tier, frozen at close
decided_by?snowflakeThe admin who last moved the candidate
decided_at?ISO8601 timestampWhen the candidate was last moved
delivered_at?ISO8601 timestampWhen the rewards were given, or the off-site reward was marked handed over
note?stringThe last staff note
premium_kept?1booleanWhether a revoke left Micup Plus days in place

1 Present only in the response to a revoke

FieldTypeDescription
seasonintegerThe season as YYYYMM
gamestringThe game kind
statusstringnone before close, building while candidates are written, built after
built_at?ISO8601 timestampWhen every candidate was written
candidatesarray[table game candidate object]Every candidate, flagged ones first, then by place
FieldTypeDescription
approvedintegerThe candidates this request approved
ValueDescription
reset_ratingThe rating of one game went back to its starting values, and this season’s leaderboard entry was removed
season_exclusionThe account was taken off one season’s leaderboard of one game
reward_revokeA reward was revoked, written by Decide table game candidate
FieldTypeDescription
idsnowflakeThe ID of the sanction
kindstringThe sanction kind
gamestringThe game kind
season?integerThe season as YYYYMM, null for reset_rating
reasonstringWhy staff applied the sanction
created_bysnowflakeThe admin who applied the sanction
created_atISO8601 timestampWhen the sanction was applied
lifted_at?ISO8601 timestampWhen the sanction was lifted
lifted_by?snowflakeThe admin who lifted the sanction
appeal_note?stringThe last appeal note
FieldTypeDescription
gamestringThe game kind
ratingnumberThe skill rating
rdnumberThe rating deviation
gamesintegerThe rated games in this game
seasonintegerThe season of season_games as YYYYMM
season_gamesintegerThe rated games in that season
league?stringThe league, null during placement games
rrintegerThe rank rating, 0 below the legend league
listedbooleanWhether the account shows on leaderboards
excluded_season?integerThe season the account is excluded from, as YYYYMM
FieldTypeDescription
gamestringThe game kind
signalscandidate signals objectThe summary of the current season’s games so far
flagsarray[string]The candidate flags those games would raise
FieldTypeDescription
ended_atISO8601 timestampWhen the game ended
gamestringThe game kind
guild_idsnowflakeThe guild the table was in
placeintegerThe account’s place in the game
playersintegerThe seated players
outcomestringwin, loss, draw or none
rated_opponentsarray[snowflake]The opponents the game was rated against
rating_beforeintegerThe rating before the game
rating_afterintegerThe rating after the game
flagsarray[string]The match flags of the game
FieldTypeDescription
ratingsarray[table game rating object]One per ranked game the account has played
analysisarray[table game analysis object]One per rating
candidatesarray[table game candidate object]The account’s candidates of the last 14 seasons, newest first
sanctionsarray[table game sanction object]Every sanction of the last 400 days, newest first
recent_historyarray[table game history entry object]The last 50 rated games of the last 90 days, newest first
GET/v1/admin/table-games/rewardsAudit reason

Returns the season rewards object. It is read from storage, not from the instance configuration cache.

StatusBodyCondition
200season rewards objectThe rewards were returned

The operation records one Admin audit entry with action view_table_game_rewards, target type table_game, target ID 0, and metadata key result_count, the number of rewards in all tiers.

60 requests per minute for each authenticated user, on the admin:table_game bucket.

PUT/v1/admin/table-games/rewardsAudit reason

Replaces the rewards of all five tiers and the showcase heading, and returns the season rewards object. A season that has already closed keeps the rewards it was closed with.

FieldTypeDescription
rank1array[season reward object]The rewards of first place
rank2array[season reward object]The rewards of second place
rank3array[season reward object]The rewards of third place
top10array[season reward object]The rewards of places 4 through 10
top100array[season reward object]The rewards of places 11 through 100
showcase_titlestringThe showcase heading, trimmed and at most 80 characters; an empty string uses the client’s translated default
  • A tier holds at most 5 rewards and at most one premium_days reward.
  • A cosmetic reward must name an avatar decoration with owned availability that is not in the shop catalog and is not a Visionary reward. Take an item off sale with Take cosmetic item off sale first.
  • A badge reward must name an existing badge that is not numbered.
  • Any other reward type, an avatar ultra, a profile effect or a nameplate included, is refused.
StatusBodyCondition
200season rewards objectThe rewards were saved
400error responseA reward is refused. errors names each refused field, as <tier>.<index>.<field>

The rewards are saved with a compare-and-set, and every API process picks them up through the instance configuration refresh. A refused request saves nothing. The operation records one entry with action update_table_game_rewards, target type table_game, target ID 0, and a <tier>_old and <tier>_new metadata key for every tier it changed. Each lists the tier’s rewards as type:value pairs, and an off-site reward as offsite alone. A changed heading adds showcase_title_old and showcase_title_new metadata keys.

60 requests per minute for each authenticated user, on the admin:table_game bucket.

GET/v1/admin/table-games/seasons/{season}/{game}Audit reason

Returns the table game season object of one season and game. A season that has not closed returns status none and no candidates.

FieldTypeDescription
seasonintegerThe season as YYYYMM (202601-209912)
gamestringThe ranked game kind: chess, dama, dama_normal, okey or okey101
StatusBodyCondition
200table game season objectThe season was returned
400error responseThe season or the game is refused

The operation records one entry with action view_table_game_season, target type table_game_season, the season as target ID, and metadata keys game and result_count, the number of candidates.

60 requests per minute for each authenticated user, on the admin:table_game bucket.

POST/v1/admin/table-games/seasons/{season}/{game}/approve-unflaggedAudit reason

Approves every candidate of one season and game that is in review with no flag, and queues each reward. Returns the bulk approve result object. Flagged candidates stay in review for one-by-one decisions.

FieldTypeDescription
seasonintegerThe season as YYYYMM (202601-209912)
gamestringThe ranked game kind
StatusBodyCondition
200bulk approve result objectThe candidates were approved
400error responseThe season or the game is refused

Each approval is a compare-and-set on review, so a candidate another admin moved first is skipped, and a repeated request approves none twice. Each approved candidate queues one delivery job. The operation records one entry with action bulk_approve_table_game_rewards, target type table_game_season, the season as target ID, and metadata keys game and approved.

60 requests per minute for each authenticated user, on the admin:table_game bucket.

POST/v1/admin/table-games/seasons/{season}/{game}/candidates/{user_id}Audit reason

Moves one candidate along its statuses, and returns the table game candidate object.

FieldTypeDescription
seasonintegerThe season as YYYYMM (202601-209912)
gamestringThe ranked game kind
user_idsnowflakeThe ID of the candidate
FieldTypeDescription
actionstringapprove, reject, mark_offsite_delivered, revoke or reconsider
note?stringA staff note (1-500 characters), required for reject and revoke
  • approve queues the delivery of the tier’s rewards. Micup Plus days, the avatar decoration and the badge are given once, however many times the job runs.
  • reject refuses the reward. An appeal reverses it with approve.
  • mark_offsite_delivered records that staff handed over the off-site reward.
  • revoke writes a reward_revoke sanction, and takes back the badge and the avatar decoration unless another delivered reward of the same season gave the account the same one. Micup Plus days stay.
  • reconsider takes an automatic refusal back to review, so a person looks at the analysis again after an objection. It is refused for an account that was gone or banned at close.
StatusBodyCondition
200table game candidate objectThe candidate was moved
400error responseA value is refused, or a reject or revoke has no note
404error responseThe account is not a candidate of that season and game, returned as NOT_FOUND
409error responseThe candidate’s status does not allow the action, or it changed during the request, returned as CONFLICT

The status moves with a compare-and-set, so two admins never both move one candidate. Only the revoke that moves the status writes its sanction and takes the items back. A revoke that fails while taking them back returns the candidate to its earlier status, so it can be sent again; the repeat writes no second sanction and takes back nothing twice. The operation records one entry with action approve_table_game_reward, reject_table_game_reward, mark_offsite_delivered_table_game_reward, revoke_table_game_reward or reconsider_table_game_reward, target type user, the ID of the account as target ID, and metadata keys season, game, status and, when given, note and premium_kept.

60 requests per minute for each authenticated user, on the admin:table_game bucket.

GET/v1/admin/users/{user_id}/table-gamesAudit reason

Returns the user table games object of an account: its ratings, an analysis of its games this season, its candidates, its sanctions, and its recent rated games.

FieldTypeDescription
user_idsnowflakeThe ID of the account
StatusBodyCondition
200user table games objectThe account’s table games were returned

An account that never played a ranked game returns empty arrays.

The operation records one entry with action view_user_table_games, target type user, the ID of the account as target ID, and metadata key result_count, the number of history entries returned.

60 requests per minute for each authenticated user, on the admin:table_game bucket.

POST/v1/admin/users/{user_id}/table-games/sanctionsAudit reason

Applies a sanction to an account in one game, and returns the table game sanction object.

FieldTypeDescription
user_idsnowflakeThe ID of the account
FieldTypeDescription
kindstringreset_rating or season_exclusion
gamestringThe ranked game kind
season?1integerThe season as YYYYMM (202601-209912)
reasonstringWhy staff apply the sanction (1-500 characters)

1 Required for season_exclusion, and ignored for reset_rating

  • reset_rating returns the rating of the game to its starting values, with placement games to play again, and removes the account from the current season’s leaderboard. Whether the account shows on leaderboards stays as it was. The rating before the reset is kept with the sanction.
  • season_exclusion removes the account from that season’s leaderboard. For the current season, the account’s later games of that season stay off the leaderboard too. For a closed season, a candidate that waits for review or delivery is rejected, and one still being analyzed is made ineligible by the analysis. A reward being given or already given is not taken back: revoke it with Decide table game candidate.
StatusBodyCondition
200table game sanction objectThe sanction was applied
400error responseA value is refused, or the season has not started
404error responseThe account has no rating in the game, returned as NOT_FOUND
409error responseThe rating kept changing during the request, returned as CONFLICT

The sanction is stored before its effect, so a request that fails can be sent again to finish it. The operation records one entry with action create_table_game_sanction, target type user, the ID of the account as target ID, and metadata keys sanction_id, kind, game, reason and, for an exclusion, season, plus revoke_needed when the excluded season’s reward was being given or already given.

60 requests per minute for each authenticated user, on the admin:table_game bucket.

POST/v1/admin/users/{user_id}/table-games/sanctions/{sanction_id}Audit reason

Lifts a season exclusion after an accepted appeal, or adds an appeal note to any sanction. Returns the table game sanction object.

FieldTypeDescription
user_idsnowflakeThe ID of the account
sanction_idsnowflakeThe ID of the sanction
FieldTypeDescription
actionstringlift or note
notestringThe appeal note (1-500 characters)

Lifting an exclusion of the current season puts the account back on the leaderboard with its next game. A closed season stays as it was frozen. To give the reward after all, approve the rejected candidate with Decide table game candidate. A rating reset and a reward revoke are never lifted.

StatusBodyCondition
200table game sanction objectThe sanction was updated
400error responseA value is refused
404error responseThe account has no such sanction, returned as NOT_FOUND
409error responseThe sanction is not a season exclusion, or it is already lifted, returned as CONFLICT

A lift is a compare-and-set, so a sanction is lifted once. The operation records one entry with action lift_table_game_sanction or note_table_game_sanction, target type user, the ID of the account as target ID, and metadata keys sanction_id, kind and note.

60 requests per minute for each authenticated user, on the admin:table_game bucket.