Find browser games on Player Two, read its game SDK docs, and run your game studio there.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Optional. Bearer p2_agent_... (an agent key from the player's studio, under Agents) for the studio's tools; or sign in by OAuth. Public tools need nothing.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Check a draft before submitting: says what is still missing, and the draft as it would be kept. Saves nothing. No key needed.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
Run in a terminal
claude mcp add --transport http mcp https://playertwo.lol/api/mcp
Headers
Authorization (optional, not in the config above): Optional. Bearer p2_agent_... (an agent key from the player's studio, under Agents) for the studio's tools; or sign in by OAuth. Public tools need nothing.Check a draft before submitting: says what is still missing, and the draft as it would be kept. Saves nothing. No key needed.
| Argument | Type | Description |
|---|---|---|
| draft* | object |
{
"type": "object",
"required": [
"draft"
],
"properties": {
"draft": {
"type": "object",
"properties": {
"v": {
"type": "number",
"const": 1
},
"x": {
"type": "string",
"description": "X handle or link."
},
"age": {
"enum": [
"13",
"16",
"18",
"all",
""
],
"type": "string",
"description": "Who it is for. Sexual content or nudity in content makes it 18 whatever is given."
},
"art": {
"type": "string",
"description": "The key art from upload_media, required: square, 2400 by 2400 at best, no title on it. The game's card (its middle two-thirds), its page's first screen in 3D and its wide picture in the store."
},
"sub": {
"type": "string",
"maxLength": 28,
"description": "A line under the name. Up to 28 characters; longer is cut."
},
"why": {
"type": "string",
"maxLength": 300,
"description": "Raise: why back it. Up to 300 characters; longer is cut."
},
"base": {
"type": "string",
"maxLength": 40,
"description": "What it is, like \"Independent studio\". Up to 40 characters; longer is cut."
},
"clip": {
"type": "string",
"description": "The launch trailer from upload_media, required (MP4 or WebM)."
},
"days": {
"type": "number",
"maximum": 120,
"minimum": 3,
"description": "Raise: how long it is open."
},
"demo": {
"type": "boolean",
"description": "Store: this is a free demo, not the finished game."
},
"face": {
"type": "object",
"required": [
"from",
"family",
"weight",
"italic",
"files"
],
"properties": {
"from": {
"enum": [
"google",
"own"
],
"type": "string"
},
"files": {
"type": "array",
"items": {
"type": "object",
"required": [
"src"
],
"properties": {
"src": {
"type": "string"
},
"range": {
"type": "string"
}
},
"additionalProperties": {}
}
},
"family": {
"type": "string"
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "number"
}
},
"description": "The typeface the name is lettered in, as Player Two keeps it (made from font).",
"additionalProperties": {}
},
"font": {
"anyOf": [
{
"type": "string",
"description": "A template (anton, bungee, bangers, cinzel, syncopate, kanit, pixel, archivo, chakra), or a font's address from upload_media."
},
{
"type": "object",
"required": [
"google"
],
"properties": {
"google": {
"type": "string"
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "number"
}
},
"description": "A Google Fonts family at one of its weights: its files are kept in Player Two's own store."
}
],
"description": "How the name is lettered."
},
"glow": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "The game's colour, #rrggbb."
},
"goal": {
"type": "number",
"maximum": 10000000,
"minimum": 1,
"description": "Raise: dollars asked."
},
"kind": {
"enum": [
"store",
"raise"
],
"type": "string",
"description": "\"store\": sold (or free) and played or downloaded from its page. \"raise\": players back a game being made. Default raise."
},
"more": {
"type": "string",
"maxLength": 700,
"description": "A second paragraph. Up to 700 characters; longer is cut."
},
"name": {
"type": "string",
"maxLength": 28,
"description": "The name as lettered on the card (uppercase); the title when empty. Up to 28 characters; longer is cut."
},
"note": {
"type": "string",
"maxLength": 900,
"description": "A note to players. Up to 900 characters; longer is cut."
},
"sign": {
"type": "string",
"maxLength": 40,
"description": "How it signs off. Up to 40 characters; longer is cut."
},
"site": {
"type": "string",
"description": "Its website."
},
"size": {
"type": "number",
"description": "The lettering's size, 0.5 to 1.6."
},
"tall": {
"type": "string",
"description": "An older listing's vertical poster (2:3): its card while it has no key art."
},
"build": {
"type": "string",
"description": "The address upload_web_build returned: a web build Player Two keeps, played at https://<slug>.playertwo.cc."
},
"depth": {
"type": "string",
"description": "The key art's depth map, made by Player Two."
},
"modes": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 10 short words (Duel, Co-op...), the main ones first."
},
"opens": {
"type": "number",
"description": "Raise: when it opens to backers (milliseconds since 1970), up to 60 days ahead."
},
"pitch": {
"type": "string",
"maxLength": 700,
"description": "What it is, in a paragraph. Up to 700 characters; longer is cut."
},
"price": {
"type": "number",
"maximum": 500,
"minimum": 0,
"description": "Store: dollars, 0 is free."
},
"share": {
"type": "number",
"maximum": 0.85,
"minimum": 0.4,
"description": "Raise with backers \"share\": the backers' share of every sale."
},
"shots": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 8 screenshots from upload_media."
},
"sound": {
"type": "boolean",
"description": "Whether the trailer's sound may play."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "The game's name. Up to 60 characters; longer is cut."
},
"today": {
"enum": [
"concept",
"prototype",
"demo",
"early"
],
"type": "string",
"description": "Raise: where the game is today."
},
"trial": {
"enum": [
0,
15,
30,
60,
90,
120
],
"type": "number",
"description": "Store, for a game that costs money and plays in the browser: a free trial in minutes, once for each player who doesn't own it (0: none; a new game left without one gets 30)."
},
"access": {
"type": "array",
"items": {
"enum": [
"Subtitles",
"Captions for sounds",
"Adjustable text size",
"Colour-blind options",
"High contrast",
"Remappable controls",
"One-handed play",
"No timed inputs needed",
"Adjustable difficulty",
"Save anytime",
"Separate volume controls",
"Narrated menus",
"Camera comfort options",
"Mouse only",
"Keyboard only",
"Touch only"
],
"type": "string"
},
"description": "What it does for players with a disability."
},
"copies": {
"type": "object",
"description": "The pictures' smaller copies, by each picture's address (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "object",
"required": [
"w",
"at"
],
"properties": {
"w": {
"type": "number"
},
"at": {
"type": "array",
"items": {
"type": "object",
"required": [
"w",
"src"
],
"properties": {
"w": {
"type": "number"
},
"src": {
"type": "string"
}
}
}
}
}
}
},
"follow": {
"type": "boolean",
"description": "With playUrl (on for a new game unless false): Player Two serves the site from https://<slug>.playertwo.cc, so saves follow players and the SDK is in its pages."
},
"genres": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 10, the main ones first (a game shows its first four), each up to 24 characters. The store's: Action, Adventure, Arcade, Arena, Casual, Co-op, Fighting, Horror, Multiplayer, Platformer, Puzzle, Racing, Roguelite, RPG, Shooter, Simulation, Social, Sports, Strategy, Survival."
},
"poster": {
"type": "string",
"description": "An older listing's main poster (16:9): its wide picture beside key art; new key art takes the place of both posters."
},
"stages": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"days": {
"type": "number",
"description": "Due this many days after the raise is funded."
},
"proof": {
"type": "string",
"maxLength": 240,
"description": "What backers will see. Up to 240 characters; longer is cut."
},
"share": {
"type": "number",
"description": "Its share of the raise, 0 to 1; all add up to 1."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "The stage. Up to 60 characters; longer is cut."
}
}
},
"description": "Raise: 1 to 8 stages."
},
"stills": {
"type": "object",
"description": "A still of each feature's video (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"studio": {
"type": "string",
"maxLength": 40,
"description": "The studio's name, required. Up to 40 characters; longer is cut."
},
"videos": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 4 gameplay videos from upload_media, after the trailer, in this order."
},
"backers": {
"enum": [
"share",
"rewards"
],
"type": "string",
"description": "Raise: what backers get, a share of every sale or rewards only."
},
"content": {
"type": "array",
"items": {
"enum": [
"Violence",
"Blood and gore",
"Sexual content",
"Nudity",
"Strong language",
"Drugs, alcohol or tobacco",
"Gambling-style play",
"Frightening scenes",
"Talking with strangers online"
],
"type": "string"
},
"description": "What it shows, for players and parents."
},
"discord": {
"type": "string",
"description": "Discord invite."
},
"playUrl": {
"type": "string",
"description": "The https address where the game is played on its own site."
},
"rewards": {
"type": "array",
"items": {
"type": "object",
"required": [
"min",
"title"
],
"properties": {
"min": {
"type": "number"
},
"body": {
"type": "string",
"maxLength": 240,
"description": "A line more. Up to 240 characters; longer is cut."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "What they get. Up to 60 characters; longer is cut."
}
}
},
"description": "Raise with backers \"rewards\": up to 8, by the least put in for each."
},
"spacing": {
"type": "string",
"maxLength": 10,
"description": "Letter spacing, as CSS. Up to 10 characters; longer is cut."
},
"tagline": {
"type": "string",
"maxLength": 90,
"description": "One line about it. Up to 90 characters; longer is cut."
},
"youtube": {
"type": "string",
"description": "YouTube channel."
},
"branches": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"goals"
],
"properties": {
"name": {
"type": "string",
"maxLength": 30,
"description": "A branch of work. Up to 30 characters; longer is cut."
},
"goals": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"now": {
"type": "string"
},
"cost": {
"type": "number"
},
"next": {
"type": "string"
},
"shot": {
"type": "number"
},
"stage": {
"type": "number"
},
"title": {
"type": "string"
}
}
}
}
}
},
"description": "Raise: what the money builds, up to 4 branches of up to 3 goals."
},
"features": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 90,
"description": "A feature with neither picture nor video: words on the page, in the game's colour. Up to 90 characters; longer is cut."
},
{
"type": "object",
"properties": {
"art": {
"type": "string",
"description": "A picture's address from upload_media, shown wide (16:9)."
},
"clip": {
"type": "string",
"description": "Or a video's address from upload_media (a picture wins when both are given)."
},
"text": {
"type": "string",
"maxLength": 90,
"description": "The feature, in a line. Up to 90 characters; longer is cut."
}
}
}
]
},
"description": "Store: up to 6."
},
"postBody": {
"type": "string",
"maxLength": 600,
"description": "The first post. Up to 600 characters; longer is cut."
},
"languages": {
"type": "array",
"items": {
"type": "object",
"required": [
"lang"
],
"properties": {
"ui": {
"type": "boolean"
},
"lang": {
"enum": [
"English",
"Spanish",
"Spanish (Latin America)",
"Portuguese (Brazil)",
"Portuguese",
"French",
"German",
"Italian",
"Dutch",
"Polish",
"Russian",
"Ukrainian",
"Turkish",
"Arabic",
"Hebrew",
"Hindi",
"Bengali",
"Thai",
"Vietnamese",
"Indonesian",
"Malay",
"Filipino",
"Japanese",
"Korean",
"Chinese (Simplified)",
"Chinese (Traditional)",
"Swedish",
"Norwegian",
"Danish",
"Finnish",
"Czech",
"Slovak",
"Hungarian",
"Romanian",
"Bulgarian",
"Greek",
"Persian"
],
"type": "string"
},
"subs": {
"type": "boolean"
},
"audio": {
"type": "boolean"
}
}
},
"description": "The languages it comes in: its words on screen (ui), voices (audio), subtitles (subs)."
},
"minTicket": {
"type": "number",
"description": "Raise: the smallest stake, dollars."
},
"platforms": {
"type": "array",
"items": {
"enum": [
"Browser",
"Windows",
"Mac",
"Linux",
"Mobile"
],
"type": "string"
},
"description": "Where it plays."
},
"postTitle": {
"type": "string",
"maxLength": 80,
"description": "The first post's title. Up to 80 characters; longer is cut."
},
"qualifier": {
"type": "string",
"maxLength": 40,
"description": "A short note after the tagline, like \"an unofficial fan game\". Up to 40 characters; longer is cut."
},
"todayLine": {
"type": "string",
"maxLength": 90,
"description": "Raise: where it is today, in a line. Up to 90 characters; longer is cut."
},
"agentNotes": {
"type": "object",
"properties": {
"goals": {
"type": "string",
"maxLength": 400,
"description": "What a player is trying to do, and how a run or a round ends. Up to 400 characters; longer is cut."
},
"controls": {
"type": "string",
"maxLength": 400,
"description": "The controls: keys, mouse, touch or gamepad, and what each does. Up to 400 characters; longer is cut."
}
},
"description": "How to play, in the developer's words: shown to agents reading the game's page (a hidden section), never to players."
},
"clipCopies": {
"type": "object",
"description": "The trailer's lighter copies (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"required": [
"h",
"src"
],
"properties": {
"h": {
"type": "number"
},
"src": {
"type": "string"
}
}
}
}
},
"controller": {
"enum": [
"full",
"partial",
""
],
"type": "string",
"description": "\"full\": it all plays with a gamepad. \"partial\": some of it needs a keyboard or mouse."
},
"multiplayer": {
"enum": [
"rooms",
"none",
"own"
],
"type": "string",
"description": "For a game hosted on Player Two: Player Two's rooms through p2.rooms (the default), single-player, or its own servers."
},
"orientation": {
"enum": [
"landscape",
"portrait",
""
],
"type": "string",
"description": "Which way a phone is held to play it: \"landscape\" (sideways) or \"portrait\" (upright); \"\" either way. A landscape game's card on X plays it sideways on a phone held upright, as X's app doesn't turn."
},
"plannedPrice": {
"type": "number",
"description": "Raise: the price it will sell at, dollars."
},
"requirements": {
"type": "object",
"properties": {
"min": {
"type": "object",
"properties": {
"os": {
"type": "string",
"maxLength": 80,
"description": "Operating system. Up to 80 characters; longer is cut."
},
"cpu": {
"type": "string",
"maxLength": 80,
"description": "Processor. Up to 80 characters; longer is cut."
},
"gpu": {
"type": "string",
"maxLength": 80,
"description": "Graphics. Up to 80 characters; longer is cut."
},
"ram": {
"type": "string",
"maxLength": 80,
"description": "Memory. Up to 80 characters; longer is cut."
},
"notes": {
"type": "string",
"maxLength": 200,
"description": "Anything else. Up to 200 characters; longer is cut."
},
"storage": {
"type": "string",
"maxLength": 80,
"description": "Disk space. Up to 80 characters; longer is cut."
}
}
},
"rec": {
"type": "object",
"properties": {
"os": {
"type": "string",
"maxLength": 80,
"description": "Operating system. Up to 80 characters; longer is cut."
},
"cpu": {
"type": "string",
"maxLength": 80,
"description": "Processor. Up to 80 characters; longer is cut."
},
"gpu": {
"type": "string",
"maxLength": 80,
"description": "Graphics. Up to 80 characters; longer is cut."
},
"ram": {
"type": "string",
"maxLength": 80,
"description": "Memory. Up to 80 characters; longer is cut."
},
"notes": {
"type": "string",
"maxLength": 200,
"description": "Anything else. Up to 200 characters; longer is cut."
},
"storage": {
"type": "string",
"maxLength": 80,
"description": "Disk space. Up to 80 characters; longer is cut."
}
}
}
},
"description": "What a computer needs for its downloads: the least, and what plays it best."
}
},
"additionalProperties": {}
}
}
}Add a leaderboard to one of the player's hosted games, or change one by its key (up to 20): which way is better, how a score reads, its bounds, the wait between scores, and whether only the game's own server sends scores (trusted). The game fills it with the SDK's scores.submit(key, value).
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| board* | object |
{
"type": "object",
"required": [
"slug",
"board"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"board": {
"type": "object",
"required": [
"key",
"name"
],
"properties": {
"key": {
"type": "string",
"maxLength": 60,
"description": "a-z, 0-9 and dashes, up to 40: what the game's code fills it by."
},
"max": {
"type": [
"number",
"null"
],
"description": "The highest score it takes."
},
"min": {
"type": [
"number",
"null"
],
"description": "The lowest score it takes."
},
"name": {
"type": "string",
"maxLength": 40,
"description": "Up to 40 characters."
},
"order": {
"enum": [
"high",
"low"
],
"type": "string",
"description": "Which way is better."
},
"format": {
"enum": [
"number",
"time",
"points"
],
"type": "string",
"description": "How a score reads: a number, a time in milliseconds, or points."
},
"trusted": {
"type": "boolean",
"description": "Only the game's own server sends its scores."
},
"cooldown": {
"type": "number",
"maximum": 86400,
"minimum": 0,
"description": "Seconds a player waits between scores."
}
}
}
}
}Add something one of the player's games sells, or change one by its key. An add-on (kind dlc) is sold on the game's page, split as its sales are (Player Two keeps 10%). Everything else is sold inside the game: the game lists them (p2.store.list) and asks to sell one (p2.store.buy), Player Two's own step takes the player's yes, and Player Two keeps 20%: a consumable (bought again and again, qty a time, used up by the game's server), an item or skin, a mod, a pack (contents: 2 to 10 of the others). Key and kind stay once a player has it; retired takes it off sale.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| product* | object |
{
"type": "object",
"required": [
"slug",
"product"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"product": {
"type": "object",
"required": [
"key",
"name",
"price"
],
"properties": {
"key": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "What the game's code asks for it by: small letters, numbers and dashes. It stays once a player has it."
},
"qty": {
"type": "integer",
"maximum": 1000,
"minimum": 1,
"description": "A consumable's: how many one purchase gives."
},
"kind": {
"enum": [
"dlc",
"consumable",
"item",
"skin",
"mod",
"pack"
],
"type": "string",
"description": "dlc (an add-on, sold on the game's page, split as its sales: 10% Player Two's), or an in-game purchase sold inside the game through p2.store (20% Player Two's): consumable, item, skin, mod, pack. dlc if not said; it stays once a player has it."
},
"name": {
"type": "string",
"maxLength": 60,
"minLength": 2
},
"about": {
"type": "string",
"maxLength": 280
},
"price": {
"type": "number",
"maximum": 500,
"minimum": 0.99,
"description": "In US dollars, $0.99 to $500."
},
"retired": {
"type": "boolean",
"description": "true takes it off sale (its owners keep it); false puts it back."
},
"contents": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40
},
"maxItems": 10,
"minItems": 2,
"description": "A pack's: the keys of 2 to 10 of the game's in-game products (no add-ons or packs)."
}
}
}
}
}Add a trophy to one of the player's hosted games, or change one by its key. Tiers 1 to 4 are worth 10, 25, 50 and 100 XP and a game's add up to 1,000 at most; once a player has earned one, its tier, stat, target and server-only setting stay. Every trophy is a relic, a small sculpture of cubes built from its sign: rows from the top on a grid of up to 16 by 16, # a cube and . none ("..#../.###./#####"), or a library sign's name (crown, rocket, gem, pad, bell, lantern, flag, fist, star, bolt, key, sword, shield, heart, moon, flame, hourglass, anchor, tower, joystick, gift); without one Player Two picks one by its key. The completion trophy (key "complete") is a crown until it is given the game's own sign: send key "complete" with a sign alone. The game earns a trophy with the SDK's trophies.unlock(key).
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| trophy* | object |
{
"type": "object",
"required": [
"slug",
"trophy"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"trophy": {
"type": "object",
"required": [
"key"
],
"properties": {
"art": {
"type": "string",
"maxLength": 600,
"description": "A picture from upload_media."
},
"how": {
"type": "string",
"maxLength": 120,
"description": "How to earn it, up to 120 characters."
},
"key": {
"type": "string",
"maxLength": 60,
"description": "a-z, 0-9 and dashes, up to 40: what the game's code earns it by. \"complete\" is the completion trophy."
},
"name": {
"type": "string",
"default": "",
"maxLength": 40,
"description": "Up to 40 characters."
},
"sign": {
"anyOf": [
{
"anyOf": [
{
"type": "string",
"maxLength": 600
},
{
"type": "array",
"items": {
"type": "string",
"maxLength": 64
},
"maxItems": 40
}
]
},
{
"type": "null"
}
],
"description": "The small picture its relic (a sculpture of cubes) is built from: rows of # (a cube) and . (none) from the top, up to 16 by 16, as one string separated by / or a list of rows; or a library sign's name (crown, rocket, gem, pad, bell, lantern, flag, fist, star, bolt, key, sword, shield, heart, moon, flame, hourglass, anchor, tower, joystick, gift). Left out, it keeps its sign; empty, Player Two picks one by its key."
},
"stat": {
"anyOf": [
{
"type": "string",
"maxLength": 60
},
{
"type": "null"
}
],
"description": "Earned by itself when this stat reaches target."
},
"tier": {
"type": "integer",
"default": 0,
"maximum": 4,
"minimum": 1,
"description": "1 to 4, worth 10, 25, 50 and 100 XP; a game's trophies add up to 1,000 XP at most."
},
"hidden": {
"type": "boolean",
"description": "Show only that there is one until it is earned."
},
"target": {
"type": [
"number",
"null"
],
"description": "A whole number, 1 or more."
},
"serverOnly": {
"type": "boolean",
"description": "Only the game's own server can give it, with a game key."
}
}
}
}
}Take one of the player's developer posts (kind devlog) off its game's page for good, by its id from list_updates: gone from the page, the feeds, the studio and the API; the notices it sent are taken out of players' lists (an email already sent stays sent); its pictures and video leave the store a day later unless another post shows them; unpinned if it was pinned. It can't be undone: only when the player asked for it. Player Two's own posts can't be deleted.
| Argument | Type | Description |
|---|---|---|
| id* | string | The post's id, from list_updates. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug",
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The post's id, from list_updates."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}Change one of the player's developer posts (kind devlog, from list_updates) by its id: its title (2 to 80), its words in Markdown (up to 10,000) and its attachments (media: the whole new list, in order, up to 4 pictures or a video and 3; the ones it had, and new ones from upload_media with game). What you leave out stays. The same rules as post_update; nobody is told again; its page says Edited after its date, and its translations are made again. A post waiting to go up (scheduled in list_updates): at moves its time, now: true posts it now (its audience told then); it isn't marked Edited. A file taken out leaves the store a day later unless another post shows it. Only what the player asked for.
| Argument | Type | Description |
|---|---|---|
| at | number | string | A post waiting to go up: its new time, as for posting (5 minutes to 90 days ahead). One already up is 409. |
| id* | string | The post's id, from list_updates. |
| now | boolean | A post waiting to go up: up now, its audience told now (Post now). One already up is 409. |
| body | string | Its words, in Markdown, as for posting (up to 10,000 characters; 2 at least unless it has media). A developer's post ("devlog") only. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| media | array |
One of the player's games as stored (drafts too), with its raise if it has one.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}Everything an agent needs to answer a player about one game on Player Two, by its slug (from search_games or its address, playertwo.lol/game/<slug>): what it is, its genres and modes, what it plays on, who it is for, its price (a sale, a trial, a raise's progress), where to play it and whether a guest can, how to play it (its controls and goals, in its developer's words), whether it is multiplayer, the Player Two services it has (trophies, leaderboards, cloud saves, add-ons), its latest updates, and how to report a bug. The same facts its page gives agents. No key needed.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>), from search_games or list_games. |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"maxLength": 80,
"description": "The game's address on Player Two (playertwo.lol/game/<slug>), from search_games or list_games."
}
}
}One of the player's games' multiplayer rooms open now (by build) and how their players' connections were over the last minute, overall and for its eight busiest rooms: ping (the middle page's and p90, ms there and back), jitter, bytes a second each way a page, corrections and rewinds a minute a page, connections dropped; whether rooms are on, the live build's room code, and the last error that code threw. What the studio's Rooms panel shows; `units` says what each figure is in. Read-only.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}A part of Player Two's developer docs, in Markdown, as the docs pages say it today: the game SDK (trophies, leaderboards, stats, cloud saves, presence, in-game purchases, multiplayer rooms and room code), hosting a web game and pushing builds, Player Two Connect for a game on its own site, travel and avatars, webhooks, and the platform's rules for developers (listing, raises, fees, agents). topic: a page and part ("/docs/sdk#rooms"), a part's id ("rooms-sync"), or a few words ("leaderboards", "push", "fees"); left out, the list of every topic. No key needed.
| Argument | Type | Description |
|---|---|---|
| topic | string | A part of the docs: a page and part ("/docs/sdk#rooms", "/docs/hosting#push"), a part's id ("call-trophies", "rooms-sync"), or a few words ("leaderboards", "cloud saves", "fees", "mcp"). Left out: the list of every topic. |
{
"type": "object",
"properties": {
"topic": {
"type": "string",
"maxLength": 200,
"description": "A part of the docs: a page and part (\"/docs/sdk#rooms\", \"/docs/hosting#push\"), a part's id (\"call-trophies\", \"rooms-sync\"), or a few words (\"leaderboards\", \"cloud saves\", \"fees\", \"mcp\"). Left out: the list of every topic."
}
}
}Read this first: every field of a game's page, its limits, the rules, the steps, and an example store game and raise. No key needed.
No arguments.
{
"type": "object",
"properties": {}
}Take a player's comment on one of the player's games' posts down (comment: its id from list_comments): out of sight for players, kept for the team and Player Two's admins, in the audit log. Only when the player asked, or it plainly breaks the rules (spam, abuse); a comment someone should look at can also be reported on the page.
| Argument | Type | Description |
|---|---|---|
| id* | string | The post's id, from list_updates. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| comment* | string | The comment's id, from list_comments. |
{
"type": "object",
"required": [
"slug",
"id",
"comment"
],
"properties": {
"id": {
"type": "string",
"description": "The post's id, from list_updates."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"comment": {
"type": "string",
"description": "The comment's id, from list_comments."
}
}
}One of the player's games' leaderboards, with how many players are on each.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}One of the player's web games' builds that are still kept (30 days after another took its place, and the last 20 always), newest first: each one's version (its developer's, or its number in the game's builds), which is live, who sent each (the player, or which agent key), its size, its files against the build before, its commit and note, the players on it now and where to try it without making it live; and the game's latest changes of build.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}Players' comments on one of the player's games' posts (id from list_updates), oldest first, the newest last, up to 200: each with its id, words, who wrote it (dev: the game's team), when, whether it was taken down, the comment it replies to, and whether it is new for the player (new: written since they last read the post's comments, not by them); how many are new; and whether the post's comments are locked. Reading them doesn't mark them read: mark_comments_read does. Agents read and look after comments; they don't write them (players do).
| Argument | Type | Description |
|---|---|---|
| id* | string | The post's id, from list_updates. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug",
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The post's id, from list_updates."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}Every game in Player Two's store (playertwo.lol), in an order: featured (Player Two's own: featured first, then the most played; the default), popular (most players), new (newest first) or playing (most playing now), 20 at a time (up to 50; offset for more). The same filters as search_games. No key needed.
| Argument | Type | Description |
|---|---|---|
| kind | string | store: games out (or coming) in the store; raise: games raising money from players while they are made. |
| genre | string | Only games with this genre, as Player Two names them (Action, Adventure, Arcade, Arena, Casual, Co-op, Fighting, Horror, Multiplayer, Platformer, Puzzle, Racing, Roguelite, RPG, Shooter, Simulation, Social, Sports, Strategy, Survival, or a game's own). |
| limit | integer | How many, 1 to 50 (20 if left out). |
| order | string | featured (Player Two's own order, the default), popular (most players), new (newest first) or playing (most playing now). |
| price | string | free, paid, or any (the default). |
| offset | integer | How many to skip, for the next page (the answer's next). |
| platform | string | Only games that play on this. |
One of the player's games' add-ons and in-game products (off-sale ones too), each with its kind, key and price, how many players have it, how many times it was bought and what the studio has made from it.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}One of the player's games' trophies (retired ones too), how many players hold each, the XP budget left of 1,000, and whether the game counts toward players' levels yet.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}One of the player's games' posts still up on its page, the pinned one first and then the newest (up to 100): each one's id (what edit_update, pin_update and delete_update take), its kind (devlog: its team wrote it, so it can be edited and deleted; release, unlock, vote and raise are Player Two's own, which can only be pinned), title, Markdown words, attachments, when it went up, when it was last edited, whether it is pinned, how many comments it has and whether they are locked.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}Lock one of the player's games' posts' comments (locked: true: no more, the ones there stay) or open them again (false).
| Argument | Type | Description |
|---|---|---|
| id* | string | The post's id, from list_updates. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| locked* | boolean | true: no more comments on this post; false opens them again. |
{
"type": "object",
"required": [
"slug",
"id",
"locked"
],
"properties": {
"id": {
"type": "string",
"description": "The post's id, from list_updates."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"locked": {
"type": "boolean",
"description": "true: no more comments on this post; false opens them again."
}
}
}Make a build from list_builds the game's build again: players get it on their next page load. The build live now stays kept, so this can be undone the same way. Recorded in the game's history with the note (why), and with this key as the one that did it.
| Argument | Type | Description |
|---|---|---|
| key* | string | The build's key, from the game's list of builds. |
| note | string | Why, kept with the change in the game's history of builds. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
{
"type": "object",
"required": [
"slug",
"key"
],
"properties": {
"key": {
"type": "string",
"maxLength": 40,
"description": "The build's key, from the game's list of builds."
},
"note": {
"type": "string",
"maxLength": 1000,
"description": "Why, kept with the change in the game's history of builds."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
}
}
}For the player, on the game's team: a post's comments (id from list_updates) read up to now (or up to until, in milliseconds: the newer ones stay new), or every post's with no id (Mark all read). Each of the team has their own: a teammate's new comments stay new. Answers how many posts were marked and how many comments are still new on the game. Mark them only once the player has seen them (or asked).
| Argument | Type | Description |
|---|---|---|
| id | string | The post's id, from list_updates; left out, every post of the game. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| until | number | Read up to this moment (milliseconds), as the comment last read was written; the newer ones stay new. Left out: up to now. |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"id": {
"type": "string",
"description": "The post's id, from list_updates; left out, every post of the game."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"until": {
"type": "number",
"description": "Read up to this moment (milliseconds), as the comment last read was written; the newer ones stay new. Left out: up to now."
}
}
}The player's studio: its games and where each stands, and whether their identity is checked (needed only for raises).
No arguments.
{
"type": "object",
"properties": {}
}Give one of the player's web games' kept builds (key from list_builds, live or not) its version: up to 32 characters of letters, digits, dots, dashes, plus signs and spaces, starting with a letter or a digit (like 1.4.0 or 2.0 beta). Shown wherever its builds are from then on; nobody is told. A push names a build as it goes up (p2 push --version); this is for one that came without (a GitHub commit's, called by its number) or a correction.
| Argument | Type | Description |
|---|---|---|
| key* | string | The build's key, from the game's list of builds. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| version* | string | Its version. A build's version is up to 32 characters: letters, digits, dots, dashes, plus signs and spaces, starting with a letter or a digit (like 1.4.0 or 2.0 beta). 422 bad-version otherwise. |
{
"type": "object",
"required": [
"slug",
"key",
"version"
],
"properties": {
"key": {
"type": "string",
"maxLength": 40,
"description": "The build's key, from the game's list of builds."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"version": {
"type": "string",
"maxLength": 32,
"description": "Its version. A build's version is up to 32 characters: letters, digits, dots, dashes, plus signs and spaces, starting with a letter or a digit (like 1.4.0 or 2.0 beta). 422 bad-version otherwise."
}
}
}Pin one of a game's posts first in its page's Updates, before the newest (pinned: true, the default), or unpin it (false). Any post, Player Two's own "Out now" too. One a game: pinning another unpins the one before. Nobody is told; visitors see Pinned on it.
| Argument | Type | Description |
|---|---|---|
| id* | string | The post's id, from list_updates. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| pinned | boolean | true pins it first (unpinning the one before: one a game); false unpins it. |
{
"type": "object",
"required": [
"slug",
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The post's id, from list_updates."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"pinned": {
"type": "boolean",
"default": true,
"description": "true pins it first (unpinning the one before: one a game); false unpins it."
}
}
}One of the player's games not out yet (kept private, or coming on a day): its "anyone with the link" playtest, as its studio's Playtesters has it. on: true turns it on (anyone who opens the link sees the game's page, a private one's too, and once signed in plays it as a tester: free, in test mode, a paid game too, from then on without the link); on: false turns it off, and every tester who came by it is taken off (invited testers stay); reset: true makes a new link, the old one stopping at once. Neither: how it stands. Answers whether it is on and the link to share while it is.
| Argument | Type | Description |
|---|---|---|
| on | boolean | true: anyone with the link plays it as a tester until it is out (signed out, they see its page and sign in to play). false: off, and every tester who came by it is taken off; invited testers stay. Turned on again, it is the same link. A game not out yet only: kept private, or coming on a day. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| reset | boolean | true: a new link. The old one, and every browser holding it, stops at once, and every tester who came by it is taken off. It stays on or off as it was. |
{
"type": "object",
"required": [
"slug"
],
"properties": {
"on": {
"type": "boolean",
"description": "true: anyone with the link plays it as a tester until it is out (signed out, they see its page and sign in to play). false: off, and every tester who came by it is taken off; invited testers stay. Turned on again, it is the same link. A game not out yet only: kept private, or coming on a day."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"reset": {
"type": "boolean",
"description": "true: a new link. The old one, and every browser holding it, stops at once, and every tester who came by it is taken off. It stays on or off as it was."
}
}
}Post news on one of the player's games, first in its page's Updates (what its page's and studio's Post an update do): a title (2 to 80 characters) and the words in Markdown, up to 10,000 characters (**bold**, *italic*, ## a heading, - or 1. lists, > a quote, [words](https://...) links, http and https only; no HTML, no pictures by Markdown), with up to 4 pictures, or a video and 3 pictures (media: addresses from upload_media with game set to this slug; the first is the post's picture in the feed). Backers, owners, wishlisters and the studio's followers are told in their notices, in plain words (none for a private game); it can be edited (edit_update), pinned (pin_update) or deleted (delete_update) after, but nobody is told again and an email sent stays sent, so post only what the player asked for. With at (milliseconds or an ISO time with its zone, 5 minutes to 90 days ahead) it waits: only the team sees it (list_updates), nobody is told until it goes up at that time, as if posted then. 20 a day a player.
| Argument | Type | Description |
|---|---|---|
| at | number | string | null | To post it later: when it goes up, in milliseconds or as an ISO time with its zone (2026-11-08T18:00:00Z), 5 minutes to 90 days ahead. Until then only its team sees it (listUpdates, its page) and nobody is told; at its time it goes up as if posted then (its date that moment) and its audience is told once. Up to 20 waiting a game. Left out: now. |
| body | string | Its words, in Markdown, up to 10,000 characters (the marks count): **bold**, *italic*, a heading (a line starting with ##), lists (- or 1.), a quote (>) and links ([words](https://...), or an address written out; http and https only). No HTML (it shows as typed) and no pictures by Markdown: those go in media. 2 characters at least, unless it has media. Its notices and emails get it as plain words, the first 240 characters. |
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
Find games on Player Two (playertwo.lol), a store of games played in the browser: by words (in a game's name, tagline, description, studio, genres, modes and features: every word must match), genre, platform, free or paid, multiplayer, store game or raise. Each game with its slug, name, tagline, studio, genres, modes, price and whether it is free, a sale, a free trial, whether it plays with others, where it plays, players, reviews and its page's address. get_game_facts tells one in full. No key needed.
| Argument | Type | Description |
|---|---|---|
| kind | string | store: games out (or coming) in the store; raise: games raising money from players while they are made. |
| genre | string | Only games with this genre, as Player Two names them (Action, Adventure, Arcade, Arena, Casual, Co-op, Fighting, Horror, Multiplayer, Platformer, Puzzle, Racing, Roguelite, RPG, Shooter, Simulation, Social, Sports, Strategy, Survival, or a game's own). |
| limit | integer | How many, 1 to 50 (20 if left out). |
| order | string | featured (Player Two's own order, the default), popular (most players), new (newest first) or playing (most playing now). |
| price | string | free, paid, or any (the default). |
| query | string | Words to find, in a game's name, tagline, description, studio, genres, modes or features (every word must match). Left out: every game the filters let through. |
Submit the player's game, for the store (kind: store) or as a raise (kind: raise). Live at once, or kept as a draft in their studio with publish: false. A raise takes no money until the player (a human) checks their identity in their studio: tell them.
| Argument | Type | Description |
|---|---|---|
| draft* | object | |
| publish | boolean | false keeps it as a draft in the studio; default true. |
| release | object | How it is listed: out now (the default), kept private, or coming on a day. |
{
"type": "object",
"required": [
"draft"
],
"properties": {
"draft": {
"type": "object",
"properties": {
"v": {
"type": "number",
"const": 1
},
"x": {
"type": "string",
"description": "X handle or link."
},
"age": {
"enum": [
"13",
"16",
"18",
"all",
""
],
"type": "string",
"description": "Who it is for. Sexual content or nudity in content makes it 18 whatever is given."
},
"art": {
"type": "string",
"description": "The key art from upload_media, required: square, 2400 by 2400 at best, no title on it. The game's card (its middle two-thirds), its page's first screen in 3D and its wide picture in the store."
},
"sub": {
"type": "string",
"maxLength": 28,
"description": "A line under the name. Up to 28 characters; longer is cut."
},
"why": {
"type": "string",
"maxLength": 300,
"description": "Raise: why back it. Up to 300 characters; longer is cut."
},
"base": {
"type": "string",
"maxLength": 40,
"description": "What it is, like \"Independent studio\". Up to 40 characters; longer is cut."
},
"clip": {
"type": "string",
"description": "The launch trailer from upload_media, required (MP4 or WebM)."
},
"days": {
"type": "number",
"maximum": 120,
"minimum": 3,
"description": "Raise: how long it is open."
},
"demo": {
"type": "boolean",
"description": "Store: this is a free demo, not the finished game."
},
"face": {
"type": "object",
"required": [
"from",
"family",
"weight",
"italic",
"files"
],
"properties": {
"from": {
"enum": [
"google",
"own"
],
"type": "string"
},
"files": {
"type": "array",
"items": {
"type": "object",
"required": [
"src"
],
"properties": {
"src": {
"type": "string"
},
"range": {
"type": "string"
}
},
"additionalProperties": {}
}
},
"family": {
"type": "string"
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "number"
}
},
"description": "The typeface the name is lettered in, as Player Two keeps it (made from font).",
"additionalProperties": {}
},
"font": {
"anyOf": [
{
"type": "string",
"description": "A template (anton, bungee, bangers, cinzel, syncopate, kanit, pixel, archivo, chakra), or a font's address from upload_media."
},
{
"type": "object",
"required": [
"google"
],
"properties": {
"google": {
"type": "string"
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "number"
}
},
"description": "A Google Fonts family at one of its weights: its files are kept in Player Two's own store."
}
],
"description": "How the name is lettered."
},
"glow": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "The game's colour, #rrggbb."
},
"goal": {
"type": "number",
"maximum": 10000000,
"minimum": 1,
"description": "Raise: dollars asked."
},
"kind": {
"enum": [
"store",
"raise"
],
"type": "string",
"description": "\"store\": sold (or free) and played or downloaded from its page. \"raise\": players back a game being made. Default raise."
},
"more": {
"type": "string",
"maxLength": 700,
"description": "A second paragraph. Up to 700 characters; longer is cut."
},
"name": {
"type": "string",
"maxLength": 28,
"description": "The name as lettered on the card (uppercase); the title when empty. Up to 28 characters; longer is cut."
},
"note": {
"type": "string",
"maxLength": 900,
"description": "A note to players. Up to 900 characters; longer is cut."
},
"sign": {
"type": "string",
"maxLength": 40,
"description": "How it signs off. Up to 40 characters; longer is cut."
},
"site": {
"type": "string",
"description": "Its website."
},
"size": {
"type": "number",
"description": "The lettering's size, 0.5 to 1.6."
},
"tall": {
"type": "string",
"description": "An older listing's vertical poster (2:3): its card while it has no key art."
},
"build": {
"type": "string",
"description": "The address upload_web_build returned: a web build Player Two keeps, played at https://<slug>.playertwo.cc."
},
"depth": {
"type": "string",
"description": "The key art's depth map, made by Player Two."
},
"modes": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 10 short words (Duel, Co-op...), the main ones first."
},
"opens": {
"type": "number",
"description": "Raise: when it opens to backers (milliseconds since 1970), up to 60 days ahead."
},
"pitch": {
"type": "string",
"maxLength": 700,
"description": "What it is, in a paragraph. Up to 700 characters; longer is cut."
},
"price": {
"type": "number",
"maximum": 500,
"minimum": 0,
"description": "Store: dollars, 0 is free."
},
"share": {
"type": "number",
"maximum": 0.85,
"minimum": 0.4,
"description": "Raise with backers \"share\": the backers' share of every sale."
},
"shots": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 8 screenshots from upload_media."
},
"sound": {
"type": "boolean",
"description": "Whether the trailer's sound may play."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "The game's name. Up to 60 characters; longer is cut."
},
"today": {
"enum": [
"concept",
"prototype",
"demo",
"early"
],
"type": "string",
"description": "Raise: where the game is today."
},
"trial": {
"enum": [
0,
15,
30,
60,
90,
120
],
"type": "number",
"description": "Store, for a game that costs money and plays in the browser: a free trial in minutes, once for each player who doesn't own it (0: none; a new game left without one gets 30)."
},
"access": {
"type": "array",
"items": {
"enum": [
"Subtitles",
"Captions for sounds",
"Adjustable text size",
"Colour-blind options",
"High contrast",
"Remappable controls",
"One-handed play",
"No timed inputs needed",
"Adjustable difficulty",
"Save anytime",
"Separate volume controls",
"Narrated menus",
"Camera comfort options",
"Mouse only",
"Keyboard only",
"Touch only"
],
"type": "string"
},
"description": "What it does for players with a disability."
},
"copies": {
"type": "object",
"description": "The pictures' smaller copies, by each picture's address (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "object",
"required": [
"w",
"at"
],
"properties": {
"w": {
"type": "number"
},
"at": {
"type": "array",
"items": {
"type": "object",
"required": [
"w",
"src"
],
"properties": {
"w": {
"type": "number"
},
"src": {
"type": "string"
}
}
}
}
}
}
},
"follow": {
"type": "boolean",
"description": "With playUrl (on for a new game unless false): Player Two serves the site from https://<slug>.playertwo.cc, so saves follow players and the SDK is in its pages."
},
"genres": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 10, the main ones first (a game shows its first four), each up to 24 characters. The store's: Action, Adventure, Arcade, Arena, Casual, Co-op, Fighting, Horror, Multiplayer, Platformer, Puzzle, Racing, Roguelite, RPG, Shooter, Simulation, Social, Sports, Strategy, Survival."
},
"poster": {
"type": "string",
"description": "An older listing's main poster (16:9): its wide picture beside key art; new key art takes the place of both posters."
},
"stages": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"days": {
"type": "number",
"description": "Due this many days after the raise is funded."
},
"proof": {
"type": "string",
"maxLength": 240,
"description": "What backers will see. Up to 240 characters; longer is cut."
},
"share": {
"type": "number",
"description": "Its share of the raise, 0 to 1; all add up to 1."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "The stage. Up to 60 characters; longer is cut."
}
}
},
"description": "Raise: 1 to 8 stages."
},
"stills": {
"type": "object",
"description": "A still of each feature's video (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"studio": {
"type": "string",
"maxLength": 40,
"description": "The studio's name, required. Up to 40 characters; longer is cut."
},
"videos": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 4 gameplay videos from upload_media, after the trailer, in this order."
},
"backers": {
"enum": [
"share",
"rewards"
],
"type": "string",
"description": "Raise: what backers get, a share of every sale or rewards only."
},
"content": {
"type": "array",
"items": {
"enum": [
"Violence",
"Blood and gore",
"Sexual content",
"Nudity",
"Strong language",
"Drugs, alcohol or tobacco",
"Gambling-style play",
"Frightening scenes",
"Talking with strangers online"
],
"type": "string"
},
"description": "What it shows, for players and parents."
},
"discord": {
"type": "string",
"description": "Discord invite."
},
"playUrl": {
"type": "string",
"description": "The https address where the game is played on its own site."
},
"rewards": {
"type": "array",
"items": {
"type": "object",
"required": [
"min",
"title"
],
"properties": {
"min": {
"type": "number"
},
"body": {
"type": "string",
"maxLength": 240,
"description": "A line more. Up to 240 characters; longer is cut."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "What they get. Up to 60 characters; longer is cut."
}
}
},
"description": "Raise with backers \"rewards\": up to 8, by the least put in for each."
},
"spacing": {
"type": "string",
"maxLength": 10,
"description": "Letter spacing, as CSS. Up to 10 characters; longer is cut."
},
"tagline": {
"type": "string",
"maxLength": 90,
"description": "One line about it. Up to 90 characters; longer is cut."
},
"youtube": {
"type": "string",
"description": "YouTube channel."
},
"branches": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"goals"
],
"properties": {
"name": {
"type": "string",
"maxLength": 30,
"description": "A branch of work. Up to 30 characters; longer is cut."
},
"goals": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"now": {
"type": "string"
},
"cost": {
"type": "number"
},
"next": {
"type": "string"
},
"shot": {
"type": "number"
},
"stage": {
"type": "number"
},
"title": {
"type": "string"
}
}
}
}
}
},
"description": "Raise: what the money builds, up to 4 branches of up to 3 goals."
},
"features": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 90,
"description": "A feature with neither picture nor video: words on the page, in the game's colour. Up to 90 characters; longer is cut."
},
{
"type": "object",
"properties": {
"art": {
"type": "string",
"description": "A picture's address from upload_media, shown wide (16:9)."
},
"clip": {
"type": "string",
"description": "Or a video's address from upload_media (a picture wins when both are given)."
},
"text": {
"type": "string",
"maxLength": 90,
"description": "The feature, in a line. Up to 90 characters; longer is cut."
}
}
}
]
},
"description": "Store: up to 6."
},
"postBody": {
"type": "string",
"maxLength": 600,
"description": "The first post. Up to 600 characters; longer is cut."
},
"languages": {
"type": "array",
"items": {
"type": "object",
"required": [
"lang"
],
"properties": {
"ui": {
"type": "boolean"
},
"lang": {
"enum": [
"English",
"Spanish",
"Spanish (Latin America)",
"Portuguese (Brazil)",
"Portuguese",
"French",
"German",
"Italian",
"Dutch",
"Polish",
"Russian",
"Ukrainian",
"Turkish",
"Arabic",
"Hebrew",
"Hindi",
"Bengali",
"Thai",
"Vietnamese",
"Indonesian",
"Malay",
"Filipino",
"Japanese",
"Korean",
"Chinese (Simplified)",
"Chinese (Traditional)",
"Swedish",
"Norwegian",
"Danish",
"Finnish",
"Czech",
"Slovak",
"Hungarian",
"Romanian",
"Bulgarian",
"Greek",
"Persian"
],
"type": "string"
},
"subs": {
"type": "boolean"
},
"audio": {
"type": "boolean"
}
}
},
"description": "The languages it comes in: its words on screen (ui), voices (audio), subtitles (subs)."
},
"minTicket": {
"type": "number",
"description": "Raise: the smallest stake, dollars."
},
"platforms": {
"type": "array",
"items": {
"enum": [
"Browser",
"Windows",
"Mac",
"Linux",
"Mobile"
],
"type": "string"
},
"description": "Where it plays."
},
"postTitle": {
"type": "string",
"maxLength": 80,
"description": "The first post's title. Up to 80 characters; longer is cut."
},
"qualifier": {
"type": "string",
"maxLength": 40,
"description": "A short note after the tagline, like \"an unofficial fan game\". Up to 40 characters; longer is cut."
},
"todayLine": {
"type": "string",
"maxLength": 90,
"description": "Raise: where it is today, in a line. Up to 90 characters; longer is cut."
},
"agentNotes": {
"type": "object",
"properties": {
"goals": {
"type": "string",
"maxLength": 400,
"description": "What a player is trying to do, and how a run or a round ends. Up to 400 characters; longer is cut."
},
"controls": {
"type": "string",
"maxLength": 400,
"description": "The controls: keys, mouse, touch or gamepad, and what each does. Up to 400 characters; longer is cut."
}
},
"description": "How to play, in the developer's words: shown to agents reading the game's page (a hidden section), never to players."
},
"clipCopies": {
"type": "object",
"description": "The trailer's lighter copies (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"required": [
"h",
"src"
],
"properties": {
"h": {
"type": "number"
},
"src": {
"type": "string"
}
}
}
}
},
"controller": {
"enum": [
"full",
"partial",
""
],
"type": "string",
"description": "\"full\": it all plays with a gamepad. \"partial\": some of it needs a keyboard or mouse."
},
"multiplayer": {
"enum": [
"rooms",
"none",
"own"
],
"type": "string",
"description": "For a game hosted on Player Two: Player Two's rooms through p2.rooms (the default), single-player, or its own servers."
},
"orientation": {
"enum": [
"landscape",
"portrait",
""
],
"type": "string",
"description": "Which way a phone is held to play it: \"landscape\" (sideways) or \"portrait\" (upright); \"\" either way. A landscape game's card on X plays it sideways on a phone held upright, as X's app doesn't turn."
},
"plannedPrice": {
"type": "number",
"description": "Raise: the price it will sell at, dollars."
},
"requirements": {
"type": "object",
"properties": {
"min": {
"type": "object",
"properties": {
"os": {
"type": "string",
"maxLength": 80,
"description": "Operating system. Up to 80 characters; longer is cut."
},
"cpu": {
"type": "string",
"maxLength": 80,
"description": "Processor. Up to 80 characters; longer is cut."
},
"gpu": {
"type": "string",
"maxLength": 80,
"description": "Graphics. Up to 80 characters; longer is cut."
},
"ram": {
"type": "string",
"maxLength": 80,
"description": "Memory. Up to 80 characters; longer is cut."
},
"notes": {
"type": "string",
"maxLength": 200,
"description": "Anything else. Up to 200 characters; longer is cut."
},
"storage": {
"type": "string",
"maxLength": 80,
"description": "Disk space. Up to 80 characters; longer is cut."
}
}
},
"rec": {
"type": "object",
"properties": {
"os": {
"type": "string",
"maxLength": 80,
"description": "Operating system. Up to 80 characters; longer is cut."
},
"cpu": {
"type": "string",
"maxLength": 80,
"description": "Processor. Up to 80 characters; longer is cut."
},
"gpu": {
"type": "string",
"maxLength": 80,
"description": "Graphics. Up to 80 characters; longer is cut."
},
"ram": {
"type": "string",
"maxLength": 80,
"description": "Memory. Up to 80 characters; longer is cut."
},
"notes": {
"type": "string",
"maxLength": 200,
"description": "Anything else. Up to 200 characters; longer is cut."
},
"storage": {
"type": "string",
"maxLength": 80,
"description": "Disk space. Up to 80 characters; longer is cut."
}
}
}
},
"description": "What a computer needs for its downloads: the least, and what plays it best."
}
},
"additionalProperties": {}
},
"publish": {
"type": "boolean",
"default": true,
"description": "false keeps it as a draft in the studio; default true."
},
"release": {
"type": "object",
"properties": {
"at": {
"type": [
"number",
"string"
],
"description": "With date: when it comes out, in milliseconds or as an ISO time, up to 365 days ahead (a time already past is now). A game with its day set: the day moved."
},
"stand": {
"enum": [
"out",
"private",
"date"
],
"type": "string",
"description": "out: listed and playable now (the default). private: its page and its play only for its team, its testers and Player Two's admins, and in no list. date: in the lists with its day and Wishlist in place of Play, played only by its team and testers until then; then out by itself, its wishlisters told. A store game only (a raise opens on its own day); once out, it stays out."
}
},
"description": "How it is listed: out now (the default), kept private, or coming on a day."
}
}
}Change one of the player's games: only the fields given change. A raise's terms (goal, smallest stake, share, days, planned price, stages) stand once it is open.
| Argument | Type | Description |
|---|---|---|
| slug* | string | The game's address on Player Two (playertwo.lol/game/<slug>). |
| draft* | object |
{
"type": "object",
"required": [
"slug",
"draft"
],
"properties": {
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"draft": {
"type": "object",
"properties": {
"v": {
"type": "number",
"const": 1
},
"x": {
"type": "string",
"description": "X handle or link."
},
"age": {
"enum": [
"13",
"16",
"18",
"all",
""
],
"type": "string",
"description": "Who it is for. Sexual content or nudity in content makes it 18 whatever is given."
},
"art": {
"type": "string",
"description": "The key art from upload_media, required: square, 2400 by 2400 at best, no title on it. The game's card (its middle two-thirds), its page's first screen in 3D and its wide picture in the store."
},
"sub": {
"type": "string",
"maxLength": 28,
"description": "A line under the name. Up to 28 characters; longer is cut."
},
"why": {
"type": "string",
"maxLength": 300,
"description": "Raise: why back it. Up to 300 characters; longer is cut."
},
"base": {
"type": "string",
"maxLength": 40,
"description": "What it is, like \"Independent studio\". Up to 40 characters; longer is cut."
},
"clip": {
"type": "string",
"description": "The launch trailer from upload_media, required (MP4 or WebM)."
},
"days": {
"type": "number",
"maximum": 120,
"minimum": 3,
"description": "Raise: how long it is open."
},
"demo": {
"type": "boolean",
"description": "Store: this is a free demo, not the finished game."
},
"face": {
"type": "object",
"required": [
"from",
"family",
"weight",
"italic",
"files"
],
"properties": {
"from": {
"enum": [
"google",
"own"
],
"type": "string"
},
"files": {
"type": "array",
"items": {
"type": "object",
"required": [
"src"
],
"properties": {
"src": {
"type": "string"
},
"range": {
"type": "string"
}
},
"additionalProperties": {}
}
},
"family": {
"type": "string"
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "number"
}
},
"description": "The typeface the name is lettered in, as Player Two keeps it (made from font).",
"additionalProperties": {}
},
"font": {
"anyOf": [
{
"type": "string",
"description": "A template (anton, bungee, bangers, cinzel, syncopate, kanit, pixel, archivo, chakra), or a font's address from upload_media."
},
{
"type": "object",
"required": [
"google"
],
"properties": {
"google": {
"type": "string"
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "number"
}
},
"description": "A Google Fonts family at one of its weights: its files are kept in Player Two's own store."
}
],
"description": "How the name is lettered."
},
"glow": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "The game's colour, #rrggbb."
},
"goal": {
"type": "number",
"maximum": 10000000,
"minimum": 1,
"description": "Raise: dollars asked."
},
"kind": {
"enum": [
"store",
"raise"
],
"type": "string",
"description": "\"store\": sold (or free) and played or downloaded from its page. \"raise\": players back a game being made. Default raise."
},
"more": {
"type": "string",
"maxLength": 700,
"description": "A second paragraph. Up to 700 characters; longer is cut."
},
"name": {
"type": "string",
"maxLength": 28,
"description": "The name as lettered on the card (uppercase); the title when empty. Up to 28 characters; longer is cut."
},
"note": {
"type": "string",
"maxLength": 900,
"description": "A note to players. Up to 900 characters; longer is cut."
},
"sign": {
"type": "string",
"maxLength": 40,
"description": "How it signs off. Up to 40 characters; longer is cut."
},
"site": {
"type": "string",
"description": "Its website."
},
"size": {
"type": "number",
"description": "The lettering's size, 0.5 to 1.6."
},
"tall": {
"type": "string",
"description": "An older listing's vertical poster (2:3): its card while it has no key art."
},
"build": {
"type": "string",
"description": "The address upload_web_build returned: a web build Player Two keeps, played at https://<slug>.playertwo.cc."
},
"depth": {
"type": "string",
"description": "The key art's depth map, made by Player Two."
},
"modes": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 10 short words (Duel, Co-op...), the main ones first."
},
"opens": {
"type": "number",
"description": "Raise: when it opens to backers (milliseconds since 1970), up to 60 days ahead."
},
"pitch": {
"type": "string",
"maxLength": 700,
"description": "What it is, in a paragraph. Up to 700 characters; longer is cut."
},
"price": {
"type": "number",
"maximum": 500,
"minimum": 0,
"description": "Store: dollars, 0 is free."
},
"share": {
"type": "number",
"maximum": 0.85,
"minimum": 0.4,
"description": "Raise with backers \"share\": the backers' share of every sale."
},
"shots": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 8 screenshots from upload_media."
},
"sound": {
"type": "boolean",
"description": "Whether the trailer's sound may play."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "The game's name. Up to 60 characters; longer is cut."
},
"today": {
"enum": [
"concept",
"prototype",
"demo",
"early"
],
"type": "string",
"description": "Raise: where the game is today."
},
"trial": {
"enum": [
0,
15,
30,
60,
90,
120
],
"type": "number",
"description": "Store, for a game that costs money and plays in the browser: a free trial in minutes, once for each player who doesn't own it (0: none; a new game left without one gets 30)."
},
"access": {
"type": "array",
"items": {
"enum": [
"Subtitles",
"Captions for sounds",
"Adjustable text size",
"Colour-blind options",
"High contrast",
"Remappable controls",
"One-handed play",
"No timed inputs needed",
"Adjustable difficulty",
"Save anytime",
"Separate volume controls",
"Narrated menus",
"Camera comfort options",
"Mouse only",
"Keyboard only",
"Touch only"
],
"type": "string"
},
"description": "What it does for players with a disability."
},
"copies": {
"type": "object",
"description": "The pictures' smaller copies, by each picture's address (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "object",
"required": [
"w",
"at"
],
"properties": {
"w": {
"type": "number"
},
"at": {
"type": "array",
"items": {
"type": "object",
"required": [
"w",
"src"
],
"properties": {
"w": {
"type": "number"
},
"src": {
"type": "string"
}
}
}
}
}
}
},
"follow": {
"type": "boolean",
"description": "With playUrl (on for a new game unless false): Player Two serves the site from https://<slug>.playertwo.cc, so saves follow players and the SDK is in its pages."
},
"genres": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 10, the main ones first (a game shows its first four), each up to 24 characters. The store's: Action, Adventure, Arcade, Arena, Casual, Co-op, Fighting, Horror, Multiplayer, Platformer, Puzzle, Racing, Roguelite, RPG, Shooter, Simulation, Social, Sports, Strategy, Survival."
},
"poster": {
"type": "string",
"description": "An older listing's main poster (16:9): its wide picture beside key art; new key art takes the place of both posters."
},
"stages": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"days": {
"type": "number",
"description": "Due this many days after the raise is funded."
},
"proof": {
"type": "string",
"maxLength": 240,
"description": "What backers will see. Up to 240 characters; longer is cut."
},
"share": {
"type": "number",
"description": "Its share of the raise, 0 to 1; all add up to 1."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "The stage. Up to 60 characters; longer is cut."
}
}
},
"description": "Raise: 1 to 8 stages."
},
"stills": {
"type": "object",
"description": "A still of each feature's video (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"studio": {
"type": "string",
"maxLength": 40,
"description": "The studio's name, required. Up to 40 characters; longer is cut."
},
"videos": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 4 gameplay videos from upload_media, after the trailer, in this order."
},
"backers": {
"enum": [
"share",
"rewards"
],
"type": "string",
"description": "Raise: what backers get, a share of every sale or rewards only."
},
"content": {
"type": "array",
"items": {
"enum": [
"Violence",
"Blood and gore",
"Sexual content",
"Nudity",
"Strong language",
"Drugs, alcohol or tobacco",
"Gambling-style play",
"Frightening scenes",
"Talking with strangers online"
],
"type": "string"
},
"description": "What it shows, for players and parents."
},
"discord": {
"type": "string",
"description": "Discord invite."
},
"playUrl": {
"type": "string",
"description": "The https address where the game is played on its own site."
},
"rewards": {
"type": "array",
"items": {
"type": "object",
"required": [
"min",
"title"
],
"properties": {
"min": {
"type": "number"
},
"body": {
"type": "string",
"maxLength": 240,
"description": "A line more. Up to 240 characters; longer is cut."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "What they get. Up to 60 characters; longer is cut."
}
}
},
"description": "Raise with backers \"rewards\": up to 8, by the least put in for each."
},
"spacing": {
"type": "string",
"maxLength": 10,
"description": "Letter spacing, as CSS. Up to 10 characters; longer is cut."
},
"tagline": {
"type": "string",
"maxLength": 90,
"description": "One line about it. Up to 90 characters; longer is cut."
},
"youtube": {
"type": "string",
"description": "YouTube channel."
},
"branches": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"goals"
],
"properties": {
"name": {
"type": "string",
"maxLength": 30,
"description": "A branch of work. Up to 30 characters; longer is cut."
},
"goals": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"now": {
"type": "string"
},
"cost": {
"type": "number"
},
"next": {
"type": "string"
},
"shot": {
"type": "number"
},
"stage": {
"type": "number"
},
"title": {
"type": "string"
}
}
}
}
}
},
"description": "Raise: what the money builds, up to 4 branches of up to 3 goals."
},
"features": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 90,
"description": "A feature with neither picture nor video: words on the page, in the game's colour. Up to 90 characters; longer is cut."
},
{
"type": "object",
"properties": {
"art": {
"type": "string",
"description": "A picture's address from upload_media, shown wide (16:9)."
},
"clip": {
"type": "string",
"description": "Or a video's address from upload_media (a picture wins when both are given)."
},
"text": {
"type": "string",
"maxLength": 90,
"description": "The feature, in a line. Up to 90 characters; longer is cut."
}
}
}
]
},
"description": "Store: up to 6."
},
"postBody": {
"type": "string",
"maxLength": 600,
"description": "The first post. Up to 600 characters; longer is cut."
},
"languages": {
"type": "array",
"items": {
"type": "object",
"required": [
"lang"
],
"properties": {
"ui": {
"type": "boolean"
},
"lang": {
"enum": [
"English",
"Spanish",
"Spanish (Latin America)",
"Portuguese (Brazil)",
"Portuguese",
"French",
"German",
"Italian",
"Dutch",
"Polish",
"Russian",
"Ukrainian",
"Turkish",
"Arabic",
"Hebrew",
"Hindi",
"Bengali",
"Thai",
"Vietnamese",
"Indonesian",
"Malay",
"Filipino",
"Japanese",
"Korean",
"Chinese (Simplified)",
"Chinese (Traditional)",
"Swedish",
"Norwegian",
"Danish",
"Finnish",
"Czech",
"Slovak",
"Hungarian",
"Romanian",
"Bulgarian",
"Greek",
"Persian"
],
"type": "string"
},
"subs": {
"type": "boolean"
},
"audio": {
"type": "boolean"
}
}
},
"description": "The languages it comes in: its words on screen (ui), voices (audio), subtitles (subs)."
},
"minTicket": {
"type": "number",
"description": "Raise: the smallest stake, dollars."
},
"platforms": {
"type": "array",
"items": {
"enum": [
"Browser",
"Windows",
"Mac",
"Linux",
"Mobile"
],
"type": "string"
},
"description": "Where it plays."
},
"postTitle": {
"type": "string",
"maxLength": 80,
"description": "The first post's title. Up to 80 characters; longer is cut."
},
"qualifier": {
"type": "string",
"maxLength": 40,
"description": "A short note after the tagline, like \"an unofficial fan game\". Up to 40 characters; longer is cut."
},
"todayLine": {
"type": "string",
"maxLength": 90,
"description": "Raise: where it is today, in a line. Up to 90 characters; longer is cut."
},
"agentNotes": {
"type": "object",
"properties": {
"goals": {
"type": "string",
"maxLength": 400,
"description": "What a player is trying to do, and how a run or a round ends. Up to 400 characters; longer is cut."
},
"controls": {
"type": "string",
"maxLength": 400,
"description": "The controls: keys, mouse, touch or gamepad, and what each does. Up to 400 characters; longer is cut."
}
},
"description": "How to play, in the developer's words: shown to agents reading the game's page (a hidden section), never to players."
},
"clipCopies": {
"type": "object",
"description": "The trailer's lighter copies (made by Player Two).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"required": [
"h",
"src"
],
"properties": {
"h": {
"type": "number"
},
"src": {
"type": "string"
}
}
}
}
},
"controller": {
"enum": [
"full",
"partial",
""
],
"type": "string",
"description": "\"full\": it all plays with a gamepad. \"partial\": some of it needs a keyboard or mouse."
},
"multiplayer": {
"enum": [
"rooms",
"none",
"own"
],
"type": "string",
"description": "For a game hosted on Player Two: Player Two's rooms through p2.rooms (the default), single-player, or its own servers."
},
"orientation": {
"enum": [
"landscape",
"portrait",
""
],
"type": "string",
"description": "Which way a phone is held to play it: \"landscape\" (sideways) or \"portrait\" (upright); \"\" either way. A landscape game's card on X plays it sideways on a phone held upright, as X's app doesn't turn."
},
"plannedPrice": {
"type": "number",
"description": "Raise: the price it will sell at, dollars."
},
"requirements": {
"type": "object",
"properties": {
"min": {
"type": "object",
"properties": {
"os": {
"type": "string",
"maxLength": 80,
"description": "Operating system. Up to 80 characters; longer is cut."
},
"cpu": {
"type": "string",
"maxLength": 80,
"description": "Processor. Up to 80 characters; longer is cut."
},
"gpu": {
"type": "string",
"maxLength": 80,
"description": "Graphics. Up to 80 characters; longer is cut."
},
"ram": {
"type": "string",
"maxLength": 80,
"description": "Memory. Up to 80 characters; longer is cut."
},
"notes": {
"type": "string",
"maxLength": 200,
"description": "Anything else. Up to 200 characters; longer is cut."
},
"storage": {
"type": "string",
"maxLength": 80,
"description": "Disk space. Up to 80 characters; longer is cut."
}
}
},
"rec": {
"type": "object",
"properties": {
"os": {
"type": "string",
"maxLength": 80,
"description": "Operating system. Up to 80 characters; longer is cut."
},
"cpu": {
"type": "string",
"maxLength": 80,
"description": "Processor. Up to 80 characters; longer is cut."
},
"gpu": {
"type": "string",
"maxLength": 80,
"description": "Graphics. Up to 80 characters; longer is cut."
},
"ram": {
"type": "string",
"maxLength": 80,
"description": "Memory. Up to 80 characters; longer is cut."
},
"notes": {
"type": "string",
"maxLength": 200,
"description": "Anything else. Up to 200 characters; longer is cut."
},
"storage": {
"type": "string",
"maxLength": 80,
"description": "Disk space. Up to 80 characters; longer is cut."
}
}
}
},
"description": "What a computer needs for its downloads: the least, and what plays it best."
}
},
"additionalProperties": {}
}
}
}Keep a picture (PNG, JPEG or WebP up to 12 MB: the key art, screenshots, a feature's picture), a trailer or a gameplay video (MP4 or WebM up to 80 MB) or a font for the name's lettering (WOFF2, WOFF, TTF or OTF up to 2 MB, checked by what it is; only a font you are allowed to use on the web) in Player Two's file store. Returns its address, for the draft's art, poster, shots, clip, videos, a feature's art, or font. With game (a slug), a picture or a video for that game's updates instead: the only kind of address post_update's media takes.
| Argument | Type | Description |
|---|---|---|
| url | string | The file's https address (preferred). |
| data | string | Or the file itself in base64, up to 3 MB. |
| game | string | For a picture or video to attach to a game's update (post_update's media): that game's slug. Kept where only its team can upload to; without it, a file can't be attached to an update. |
| filename | string | Its name, when sent as data. |
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"maxLength": 2000,
"description": "The file's https address (preferred)."
},
"data": {
"type": "string",
"maxLength": 4500000,
"description": "Or the file itself in base64, up to 3 MB."
},
"game": {
"type": "string",
"maxLength": 80,
"description": "For a picture or video to attach to a game's update (post_update's media): that game's slug. Kept where only its team can upload to; without it, a file can't be attached to an update."
},
"filename": {
"type": "string",
"maxLength": 120,
"description": "Its name, when sent as data."
}
}
}Keep a game played in the browser: a .zip with index.html at its top (up to 100 MB), or a single .html page. Returns the address to put in the draft's build. version (optional): what the build is called, up to 32 characters of letters, digits, dots, dashes, plus signs and spaces, starting with a letter or a digit (like 1.4.0); left out, it is called by its number in its game's builds ("12") once the draft names it.
| Argument | Type | Description |
|---|---|---|
| url | string | The file's https address (preferred). |
| data | string | Or the file itself in base64, up to 3 MB. |
| version | any | Its version, shown with it in the studio and wherever its builds are listed, once a game's draft names it. A build's version is up to 32 characters: letters, digits, dots, dashes, plus signs and spaces, starting with a letter or a digit (like 1.4.0 or 2.0 beta). Left out, the build is called by its number in its game's builds (1 for its first: "12"). 422 bad-version when it breaks the rule. |
| filename | string | Its name, when sent as data. |
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"maxLength": 2000,
"description": "The file's https address (preferred)."
},
"data": {
"type": "string",
"maxLength": 4500000,
"description": "Or the file itself in base64, up to 3 MB."
},
"version": {
"anyOf": [
{
"type": "string",
"maxLength": 200
},
{
"type": "null"
}
],
"pattern": "^[A-Za-z0-9][A-Za-z0-9.+\\- ]*$",
"maxLength": 32,
"description": "Its version, shown with it in the studio and wherever its builds are listed, once a game's draft names it. A build's version is up to 32 characters: letters, digits, dots, dashes, plus signs and spaces, starting with a letter or a digit (like 1.4.0 or 2.0 beta). Left out, the build is called by its number in its game's builds (1 for its first: \"12\"). 422 bad-version when it breaks the rule."
},
"filename": {
"type": "string",
"maxLength": 120,
"description": "Its name, when sent as data."
}
}
}What Player Two offers a game's developer, as its docs state it, each fact with its link: what it keeps of sales, in-game purchases and raises, how a game gets there (the form, an agent, a zip, a pushed folder, GitHub, its own site served), and everything a game gets (store page, hosting, SDK, multiplayer rooms, trophies, leaderboards, saves, purchases, webhooks, MCP). No key needed.
No arguments.
{
"type": "object",
"properties": {}
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 8, 2026.
| Its attachments in their new order, the whole list (the ones it had that you keep, from listUpdates, and new ones from uploadMedia with game): up to 4 pictures, or a video and 3. [] takes them all out. Left out, they stay. A file taken out leaves the store a day later, unless another of the game's posts shows it. |
| title | string | Its title, 2 to 80 characters. |
{
"type": "object",
"required": [
"slug",
"id"
],
"properties": {
"at": {
"type": [
"number",
"string"
],
"description": "A post waiting to go up: its new time, as for posting (5 minutes to 90 days ahead). One already up is 409."
},
"id": {
"type": "string",
"description": "The post's id, from list_updates."
},
"now": {
"type": "boolean",
"const": true,
"description": "A post waiting to go up: up now, its audience told now (Post now). One already up is 409."
},
"body": {
"type": "string",
"maxLength": 10000,
"description": "Its words, in Markdown, as for posting (up to 10,000 characters; 2 at least unless it has media). A developer's post (\"devlog\") only."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"media": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 600
},
{
"type": "object",
"required": [
"src"
],
"properties": {
"h": {
"type": "integer"
},
"w": {
"type": "integer"
},
"src": {
"type": "string",
"maxLength": 600,
"description": "Its address, from upload_media with game."
},
"kind": {
"enum": [
"image",
"video"
],
"type": "string",
"description": "Read from the file; said here or not."
},
"still": {
"type": "string",
"maxLength": 600,
"description": "A video's first frame, a picture uploaded the same way: shown until it plays."
},
"copies": {
"type": "object",
"required": [
"w",
"at"
],
"properties": {
"w": {
"type": "integer"
},
"at": {
"type": "array",
"items": {
"type": "object",
"required": [
"w",
"src"
],
"properties": {
"w": {
"type": "integer"
},
"src": {
"type": "string",
"maxLength": 600
}
}
},
"maxItems": 6
}
},
"description": "A picture's smaller copies (the composer makes them as it uploads), uploaded the same way."
}
}
}
]
},
"maxItems": 4,
"description": "Its attachments in their new order, the whole list (the ones it had that you keep, from listUpdates, and new ones from uploadMedia with game): up to 4 pictures, or a video and 3. [] takes them all out. Left out, they stay. A file taken out leaves the store a day later, unless another of the game's posts shows it."
},
"title": {
"type": "string",
"maxLength": 80,
"minLength": 2,
"description": "Its title, 2 to 80 characters."
}
}
}| multiplayer |
| boolean |
| true: only games played with others (by their genres and modes, or their own servers); false: only the others. |
{
"type": "object",
"properties": {
"kind": {
"enum": [
"store",
"raise"
],
"type": "string",
"description": "store: games out (or coming) in the store; raise: games raising money from players while they are made."
},
"genre": {
"type": "string",
"maxLength": 40,
"description": "Only games with this genre, as Player Two names them (Action, Adventure, Arcade, Arena, Casual, Co-op, Fighting, Horror, Multiplayer, Platformer, Puzzle, Racing, Roguelite, RPG, Shooter, Simulation, Social, Sports, Strategy, Survival, or a game's own)."
},
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "How many, 1 to 50 (20 if left out)."
},
"order": {
"enum": [
"featured",
"popular",
"new",
"playing"
],
"type": "string",
"description": "featured (Player Two's own order, the default), popular (most players), new (newest first) or playing (most playing now)."
},
"price": {
"enum": [
"free",
"paid",
"any"
],
"type": "string",
"description": "free, paid, or any (the default)."
},
"offset": {
"type": "integer",
"maximum": 10000,
"minimum": 0,
"description": "How many to skip, for the next page (the answer's next)."
},
"platform": {
"enum": [
"Browser",
"Windows",
"Mac",
"Linux",
"Mobile"
],
"type": "string",
"description": "Only games that play on this."
},
"multiplayer": {
"type": "boolean",
"description": "true: only games played with others (by their genres and modes, or their own servers); false: only the others."
}
}
}| media | array | Up to 4 pictures (PNG, JPEG or WebP, 12 MB each), or a video (MP4, WebM or MOV, 80 MB) and up to 3 pictures, in order: the first is the post's picture in the feed, the rest open from it. Each uploaded for this game (upload_media with game); any other address is refused. |
| title* | string | Its title, 2 to 80 characters. |
{
"type": "object",
"required": [
"slug",
"title"
],
"properties": {
"at": {
"type": [
"number",
"string",
"null"
],
"description": "To post it later: when it goes up, in milliseconds or as an ISO time with its zone (2026-11-08T18:00:00Z), 5 minutes to 90 days ahead. Until then only its team sees it (listUpdates, its page) and nobody is told; at its time it goes up as if posted then (its date that moment) and its audience is told once. Up to 20 waiting a game. Left out: now."
},
"body": {
"type": "string",
"default": "",
"maxLength": 10000,
"description": "Its words, in Markdown, up to 10,000 characters (the marks count): **bold**, *italic*, a heading (a line starting with ##), lists (- or 1.), a quote (>) and links ([words](https://...), or an address written out; http and https only). No HTML (it shows as typed) and no pictures by Markdown: those go in media. 2 characters at least, unless it has media. Its notices and emails get it as plain words, the first 240 characters."
},
"slug": {
"type": "string",
"description": "The game's address on Player Two (playertwo.lol/game/<slug>)."
},
"media": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 600
},
{
"type": "object",
"required": [
"src"
],
"properties": {
"h": {
"type": "integer"
},
"w": {
"type": "integer"
},
"src": {
"type": "string",
"maxLength": 600,
"description": "Its address, from upload_media with game."
},
"kind": {
"enum": [
"image",
"video"
],
"type": "string",
"description": "Read from the file; said here or not."
},
"still": {
"type": "string",
"maxLength": 600,
"description": "A video's first frame, a picture uploaded the same way: shown until it plays."
},
"copies": {
"type": "object",
"required": [
"w",
"at"
],
"properties": {
"w": {
"type": "integer"
},
"at": {
"type": "array",
"items": {
"type": "object",
"required": [
"w",
"src"
],
"properties": {
"w": {
"type": "integer"
},
"src": {
"type": "string",
"maxLength": 600
}
}
},
"maxItems": 6
}
},
"description": "A picture's smaller copies (the composer makes them as it uploads), uploaded the same way."
}
}
}
]
},
"maxItems": 4,
"description": "Up to 4 pictures (PNG, JPEG or WebP, 12 MB each), or a video (MP4, WebM or MOV, 80 MB) and up to 3 pictures, in order: the first is the post's picture in the feed, the rest open from it. Each uploaded for this game (upload_media with game); any other address is refused."
},
"title": {
"type": "string",
"maxLength": 80,
"minLength": 2,
"description": "Its title, 2 to 80 characters."
}
}
}| offset | integer | How many to skip, for the next page (the answer's next). |
| platform | string | Only games that play on this. |
| multiplayer | boolean | true: only games played with others (by their genres and modes, or their own servers); false: only the others. |
{
"type": "object",
"properties": {
"kind": {
"enum": [
"store",
"raise"
],
"type": "string",
"description": "store: games out (or coming) in the store; raise: games raising money from players while they are made."
},
"genre": {
"type": "string",
"maxLength": 40,
"description": "Only games with this genre, as Player Two names them (Action, Adventure, Arcade, Arena, Casual, Co-op, Fighting, Horror, Multiplayer, Platformer, Puzzle, Racing, Roguelite, RPG, Shooter, Simulation, Social, Sports, Strategy, Survival, or a game's own)."
},
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "How many, 1 to 50 (20 if left out)."
},
"order": {
"enum": [
"featured",
"popular",
"new",
"playing"
],
"type": "string",
"description": "featured (Player Two's own order, the default), popular (most players), new (newest first) or playing (most playing now)."
},
"price": {
"enum": [
"free",
"paid",
"any"
],
"type": "string",
"description": "free, paid, or any (the default)."
},
"query": {
"type": "string",
"maxLength": 200,
"description": "Words to find, in a game's name, tagline, description, studio, genres, modes or features (every word must match). Left out: every game the filters let through."
},
"offset": {
"type": "integer",
"maximum": 10000,
"minimum": 0,
"description": "How many to skip, for the next page (the answer's next)."
},
"platform": {
"enum": [
"Browser",
"Windows",
"Mac",
"Linux",
"Mobile"
],
"type": "string",
"description": "Only games that play on this."
},
"multiplayer": {
"type": "boolean",
"description": "true: only games played with others (by their genres and modes, or their own servers); false: only the others."
}
}
}