[{"data":1,"prerenderedAt":1883},["ShallowReactive",2],{"docs-navigation":3,"docs-page:\u002Fdocs\u002Fapi\u002Fassets":401},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","\u002Fdocs","docs",[9,12,44,64,254,300,349,375],{"title":10,"path":6,"stem":11},"Overview","docs\u002Findex",{"title":13,"path":14,"stem":15,"children":16,"order":18},"API Overview","\u002Fdocs\u002Fapi","docs\u002Fapi\u002Findex",[17,19,24,29,34,39],{"title":13,"path":14,"stem":15,"order":18},7,{"title":20,"path":21,"stem":22,"order":23},"Assets API","\u002Fdocs\u002Fapi\u002Fassets","docs\u002Fapi\u002Fassets",3,{"title":25,"path":26,"stem":27,"order":28},"Authentication","\u002Fdocs\u002Fapi\u002Fauthentication","docs\u002Fapi\u002Fauthentication",1,{"title":30,"path":31,"stem":32,"order":33},"Components API","\u002Fdocs\u002Fapi\u002Fcomponents","docs\u002Fapi\u002Fcomponents",4,{"title":35,"path":36,"stem":37,"order":38},"Error Handling","\u002Fdocs\u002Fapi\u002Ferrors","docs\u002Fapi\u002Ferrors",5,{"title":40,"path":41,"stem":42,"order":43},"Games API","\u002Fdocs\u002Fapi\u002Fgames","docs\u002Fapi\u002Fgames",2,{"title":45,"path":46,"stem":47,"children":48,"order":38},"Automation","\u002Fdocs\u002Fautomation","docs\u002Fautomation\u002Findex",[49,50,60],{"title":45,"path":46,"stem":47,"order":38},{"title":51,"path":52,"stem":53,"children":54,"order":43},"Sequences","\u002Fdocs\u002Fautomation\u002Fsequences","docs\u002Fautomation\u002Fsequences\u002Findex",[55,56],{"title":51,"path":52,"stem":53,"order":43},{"title":57,"path":58,"stem":59},"Steps","\u002Fdocs\u002Fautomation\u002Fsequences\u002Fsteps","docs\u002Fautomation\u002Fsequences\u002Fsteps",{"title":61,"path":62,"stem":63,"order":28},"Triggers","\u002Fdocs\u002Fautomation\u002Ftriggers","docs\u002Fautomation\u002Ftriggers",{"title":65,"path":66,"stem":67,"children":68,"order":33},"Entities","\u002Fdocs\u002Fentities","docs\u002Fentities\u002Findex",[69,70,160,202],{"title":65,"path":66,"stem":67,"order":33},{"title":71,"path":72,"stem":73,"children":74},"Pieces","\u002Fdocs\u002Fentities\u002Fpieces","docs\u002Fentities\u002F01.pieces\u002Findex",[75,76,90,104,138],{"title":71,"path":72,"stem":73},{"title":77,"path":78,"stem":79,"children":80},"Dice","\u002Fdocs\u002Fentities\u002Fpieces\u002Fdice","docs\u002Fentities\u002F01.pieces\u002Fdice\u002Findex",[81,82,86],{"title":77,"path":78,"stem":79},{"title":83,"path":84,"stem":85},"Polyhedral Die","\u002Fdocs\u002Fentities\u002Fpieces\u002Fdice\u002Fpolyhedral-die","docs\u002Fentities\u002F01.pieces\u002Fdice\u002Fpolyhedral-die",{"title":87,"path":88,"stem":89},"Spinner","\u002Fdocs\u002Fentities\u002Fpieces\u002Fdice\u002Fspinner","docs\u002Fentities\u002F01.pieces\u002Fdice\u002Fspinner",{"title":91,"path":92,"stem":93,"children":94},"Tiles and Stacks","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftiles-and-stacks","docs\u002Fentities\u002F01.pieces\u002Ftiles-and-stacks\u002Findex",[95,96,100],{"title":91,"path":92,"stem":93},{"title":97,"path":98,"stem":99},"Stack","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftiles-and-stacks\u002Fstack","docs\u002Fentities\u002F01.pieces\u002Ftiles-and-stacks\u002Fstack",{"title":101,"path":102,"stem":103},"Tile","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftiles-and-stacks\u002Ftile","docs\u002Fentities\u002F01.pieces\u002Ftiles-and-stacks\u002Ftile",{"title":105,"path":106,"stem":107,"children":108},"Tokens","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftokens","docs\u002Fentities\u002F01.pieces\u002Ftokens\u002Findex",[109,110,114,118,122,126,130,134],{"title":105,"path":106,"stem":107},{"title":111,"path":112,"stem":113},"Block","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftokens\u002Fblock","docs\u002Fentities\u002F01.pieces\u002Ftokens\u002Fblock",{"title":115,"path":116,"stem":117},"Disc","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftokens\u002Fdisc","docs\u002Fentities\u002F01.pieces\u002Ftokens\u002Fdisc",{"title":119,"path":120,"stem":121},"Image Token","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftokens\u002Fimage-token","docs\u002Fentities\u002F01.pieces\u002Ftokens\u002Fimage-token",{"title":123,"path":124,"stem":125},"Model Token","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftokens\u002Fmodel-token","docs\u002Fentities\u002F01.pieces\u002Ftokens\u002Fmodel-token",{"title":127,"path":128,"stem":129},"Pawn","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftokens\u002Fpawn","docs\u002Fentities\u002F01.pieces\u002Ftokens\u002Fpawn",{"title":131,"path":132,"stem":133},"Pyramid","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftokens\u002Fpyramid","docs\u002Fentities\u002F01.pieces\u002Ftokens\u002Fpyramid",{"title":135,"path":136,"stem":137},"Ring","\u002Fdocs\u002Fentities\u002Fpieces\u002Ftokens\u002Fring","docs\u002Fentities\u002F01.pieces\u002Ftokens\u002Fring",{"title":139,"path":140,"stem":141,"children":142},"Utility Pieces","\u002Fdocs\u002Fentities\u002Fpieces\u002Futility-pieces","docs\u002Fentities\u002F01.pieces\u002Futility-pieces\u002Findex",[143,144,148,152,156],{"title":139,"path":140,"stem":141},{"title":145,"path":146,"stem":147},"Bag","\u002Fdocs\u002Fentities\u002Fpieces\u002Futility-pieces\u002Fbag","docs\u002Fentities\u002F01.pieces\u002Futility-pieces\u002Fbag",{"title":149,"path":150,"stem":151},"Counter","\u002Fdocs\u002Fentities\u002Fpieces\u002Futility-pieces\u002Fcounter","docs\u002Fentities\u002F01.pieces\u002Futility-pieces\u002Fcounter",{"title":153,"path":154,"stem":155},"Timer","\u002Fdocs\u002Fentities\u002Fpieces\u002Futility-pieces\u002Ftimer","docs\u002Fentities\u002F01.pieces\u002Futility-pieces\u002Ftimer",{"title":157,"path":158,"stem":159},"Token Bowl","\u002Fdocs\u002Fentities\u002Fpieces\u002Futility-pieces\u002Ftoken-bowl","docs\u002Fentities\u002F01.pieces\u002Futility-pieces\u002Ftoken-bowl",{"title":161,"path":162,"stem":163,"children":164},"Spaces","\u002Fdocs\u002Fentities\u002Fspaces","docs\u002Fentities\u002F02.spaces\u002Findex",[165,166,180],{"title":161,"path":162,"stem":163},{"title":167,"path":168,"stem":169,"children":170},"Layouts","\u002Fdocs\u002Fentities\u002Fspaces\u002Flayouts","docs\u002Fentities\u002F02.spaces\u002Flayouts\u002Findex",[171,172,176],{"title":167,"path":168,"stem":169},{"title":173,"path":174,"stem":175},"Hex Grid","\u002Fdocs\u002Fentities\u002Fspaces\u002Flayouts\u002Fhex-grid","docs\u002Fentities\u002F02.spaces\u002Flayouts\u002Fhex-grid",{"title":177,"path":178,"stem":179},"Square Grid","\u002Fdocs\u002Fentities\u002Fspaces\u002Flayouts\u002Fsquare-grid","docs\u002Fentities\u002F02.spaces\u002Flayouts\u002Fsquare-grid",{"title":181,"path":182,"stem":183,"children":184},"Placement Spaces","\u002Fdocs\u002Fentities\u002Fspaces\u002Fplacement-spaces","docs\u002Fentities\u002F02.spaces\u002Fplacement-spaces\u002Findex",[185,186,190,194,198],{"title":181,"path":182,"stem":183},{"title":187,"path":188,"stem":189},"Box Space","\u002Fdocs\u002Fentities\u002Fspaces\u002Fplacement-spaces\u002Fbox-space","docs\u002Fentities\u002F02.spaces\u002Fplacement-spaces\u002Fbox-space",{"title":191,"path":192,"stem":193},"Hex Space","\u002Fdocs\u002Fentities\u002Fspaces\u002Fplacement-spaces\u002Fhex-space","docs\u002Fentities\u002F02.spaces\u002Fplacement-spaces\u002Fhex-space",{"title":195,"path":196,"stem":197},"Orb Space","\u002Fdocs\u002Fentities\u002Fspaces\u002Fplacement-spaces\u002Forb-space","docs\u002Fentities\u002F02.spaces\u002Fplacement-spaces\u002Forb-space",{"title":199,"path":200,"stem":201},"Point Space","\u002Fdocs\u002Fentities\u002Fspaces\u002Fplacement-spaces\u002Fpoint-space","docs\u002Fentities\u002F02.spaces\u002Fplacement-spaces\u002Fpoint-space",{"title":203,"path":204,"stem":205,"children":206},"Annotations","\u002Fdocs\u002Fentities\u002Fannotations","docs\u002Fentities\u002F03.annotations\u002Findex",[207,208,218,244],{"title":203,"path":204,"stem":205},{"title":209,"path":210,"stem":211,"children":212},"Freehand Annotations","\u002Fdocs\u002Fentities\u002Fannotations\u002Ffreehand-annotations","docs\u002Fentities\u002F03.annotations\u002Ffreehand-annotations\u002Findex",[213,214],{"title":209,"path":210,"stem":211},{"title":215,"path":216,"stem":217},"Freehand Annotation","\u002Fdocs\u002Fentities\u002Fannotations\u002Ffreehand-annotations\u002Ffreehand-annotation","docs\u002Fentities\u002F03.annotations\u002Ffreehand-annotations\u002Ffreehand-annotation",{"title":219,"path":220,"stem":221,"children":222},"Shape Annotations","\u002Fdocs\u002Fentities\u002Fannotations\u002Fshape-annotations","docs\u002Fentities\u002F03.annotations\u002Fshape-annotations\u002Findex",[223,224,228,232,236,240],{"title":219,"path":220,"stem":221},{"title":225,"path":226,"stem":227},"Arrow Annotation","\u002Fdocs\u002Fentities\u002Fannotations\u002Fshape-annotations\u002Farrow-annotation","docs\u002Fentities\u002F03.annotations\u002Fshape-annotations\u002Farrow-annotation",{"title":229,"path":230,"stem":231},"Box Annotation","\u002Fdocs\u002Fentities\u002Fannotations\u002Fshape-annotations\u002Fbox-annotation","docs\u002Fentities\u002F03.annotations\u002Fshape-annotations\u002Fbox-annotation",{"title":233,"path":234,"stem":235},"Hex Annotation","\u002Fdocs\u002Fentities\u002Fannotations\u002Fshape-annotations\u002Fhex-annotation","docs\u002Fentities\u002F03.annotations\u002Fshape-annotations\u002Fhex-annotation",{"title":237,"path":238,"stem":239},"Orb Annotation","\u002Fdocs\u002Fentities\u002Fannotations\u002Fshape-annotations\u002Forb-annotation","docs\u002Fentities\u002F03.annotations\u002Fshape-annotations\u002Forb-annotation",{"title":241,"path":242,"stem":243},"Triangle Annotation","\u002Fdocs\u002Fentities\u002Fannotations\u002Fshape-annotations\u002Ftriangle-annotation","docs\u002Fentities\u002F03.annotations\u002Fshape-annotations\u002Ftriangle-annotation",{"title":245,"path":246,"stem":247,"children":248},"Text Annotations","\u002Fdocs\u002Fentities\u002Fannotations\u002Ftext-annotations","docs\u002Fentities\u002F03.annotations\u002Ftext-annotations\u002Findex",[249,250],{"title":245,"path":246,"stem":247},{"title":251,"path":252,"stem":253},"Text Annotation","\u002Fdocs\u002Fentities\u002Fannotations\u002Ftext-annotations\u002Ftext-annotation","docs\u002Fentities\u002F03.annotations\u002Ftext-annotations\u002Ftext-annotation",{"title":255,"path":256,"stem":257,"children":258,"order":28},"Getting Started","\u002Fdocs\u002Fgetting-started","docs\u002Fgetting-started\u002Findex",[259,260,264,268,296],{"title":255,"path":256,"stem":257,"order":28},{"title":261,"path":262,"stem":263,"order":43},"Tutorial 2: Build a Deck of Cards","\u002Fdocs\u002Fgetting-started\u002Fbuild-a-deck-of-cards","docs\u002Fgetting-started\u002Fbuild-a-deck-of-cards",{"title":265,"path":266,"stem":267,"order":23},"Tutorial 3: Use Your Own Images","\u002Fdocs\u002Fgetting-started\u002Fcustom-images","docs\u002Fgetting-started\u002Fcustom-images",{"title":269,"path":270,"stem":271,"children":272,"order":274},"Why Playtest Parlor?","\u002Fdocs\u002Fgetting-started\u002Fwhy-playtest-parlor","docs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Findex",[273,275,279,283,287,291],{"title":269,"path":270,"stem":271,"order":274},-2,{"title":276,"path":277,"stem":278,"order":33},"Compared to In-Person Playtesting","\u002Fdocs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcompared-to-in-person","docs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcompared-to-in-person",{"title":280,"path":281,"stem":282,"order":23},"Compared to PlayingCards.io","\u002Fdocs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcompared-to-playingcards-io","docs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcompared-to-playingcards-io",{"title":284,"path":285,"stem":286,"order":43},"Compared to Screentop.gg","\u002Fdocs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcompared-to-screentop","docs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcompared-to-screentop",{"title":288,"path":289,"stem":290,"order":28},"Compared to Tabletop Simulator","\u002Fdocs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcompared-to-tts","docs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcompared-to-tts",{"title":292,"path":293,"stem":294,"order":295},"Platform Comparison","\u002Fdocs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcomparison-matrix","docs\u002Fgetting-started\u002Fwhy-playtest-parlor\u002Fcomparison-matrix",0,{"title":297,"path":298,"stem":299,"order":28},"Tutorial 1: Your First Game","\u002Fdocs\u002Fgetting-started\u002Fyour-first-game","docs\u002Fgetting-started\u002Fyour-first-game",{"title":301,"path":302,"stem":303,"children":304,"order":43},"Interface","\u002Fdocs\u002Finterface","docs\u002Finterface\u002Findex",[305,306,310,315,319,323,328,332,336,341,345],{"title":301,"path":302,"stem":303,"order":43},{"title":307,"path":308,"stem":309,"order":33},"The Action Dock","\u002Fdocs\u002Finterface\u002Faction-dock","docs\u002Finterface\u002Faction-dock",{"title":311,"path":312,"stem":313,"order":314},"Finding Your Discord User ID","\u002Fdocs\u002Finterface\u002Fdiscord-id","docs\u002Finterface\u002Fdiscord-id",10,{"title":316,"path":317,"stem":318,"order":18},"The Entity Browser","\u002Fdocs\u002Finterface\u002Fentity-browser","docs\u002Finterface\u002Fentity-browser",{"title":320,"path":321,"stem":322,"order":38},"The Minimap","\u002Fdocs\u002Finterface\u002Fminimap","docs\u002Finterface\u002Fminimap",{"title":324,"path":325,"stem":326,"order":327},"The Player Hand","\u002Fdocs\u002Finterface\u002Fplayer-hand","docs\u002Finterface\u002Fplayer-hand",6,{"title":329,"path":330,"stem":331,"order":23},"The Players Panel","\u002Fdocs\u002Finterface\u002Fplayers-panel","docs\u002Finterface\u002Fplayers-panel",{"title":333,"path":334,"stem":335},"Sequences Panel","\u002Fdocs\u002Finterface\u002Fsequences-panel","docs\u002Finterface\u002Fsequences-panel",{"title":337,"path":338,"stem":339,"order":340},"Session Notebook","\u002Fdocs\u002Finterface\u002Fsession-notebook","docs\u002Finterface\u002Fsession-notebook",8,{"title":342,"path":343,"stem":344,"order":28},"The Table","\u002Fdocs\u002Finterface\u002Ftable","docs\u002Finterface\u002Ftable",{"title":346,"path":347,"stem":348,"order":43},"The Toolbar","\u002Fdocs\u002Finterface\u002Ftoolbar","docs\u002Finterface\u002Ftoolbar",{"title":350,"path":351,"stem":352,"children":353,"order":23},"Playtests","\u002Fdocs\u002Fplaytests","docs\u002Fplaytests\u002Findex",[354,355,359,363,367,371],{"title":350,"path":351,"stem":352,"order":23},{"title":356,"path":357,"stem":358,"order":43},"Inviting players","\u002Fdocs\u002Fplaytests\u002Finviting-players","docs\u002Fplaytests\u002Finviting-players",{"title":360,"path":361,"stem":362,"order":38},"Player count guidelines","\u002Fdocs\u002Fplaytests\u002Fplayer-count-guidelines","docs\u002Fplaytests\u002Fplayer-count-guidelines",{"title":364,"path":365,"stem":366,"order":33},"Reviewing outcomes","\u002Fdocs\u002Fplaytests\u002Freviewing-outcomes","docs\u002Fplaytests\u002Freviewing-outcomes",{"title":368,"path":369,"stem":370,"order":28},"Starting a playtest","\u002Fdocs\u002Fplaytests\u002Fstarting-a-playtest","docs\u002Fplaytests\u002Fstarting-a-playtest",{"title":372,"path":373,"stem":374,"order":23},"Surveys","\u002Fdocs\u002Fplaytests\u002Fsurveys","docs\u002Fplaytests\u002Fsurveys",{"title":376,"path":377,"stem":378,"children":379,"order":43},"Setting up a Table","\u002Fdocs\u002Fsetting-up-a-table","docs\u002Fsetting-up-a-table\u002Findex",[380,381,385,389,393,397],{"title":376,"path":377,"stem":378,"order":43},{"title":382,"path":383,"stem":384,"order":28},"Adding pieces to a table","\u002Fdocs\u002Fsetting-up-a-table\u002Fadding-pieces-to-a-table","docs\u002Fsetting-up-a-table\u002Fadding-pieces-to-a-table",{"title":386,"path":387,"stem":388,"order":43},"Building your first table layout","\u002Fdocs\u002Fsetting-up-a-table\u002Fbuilding-your-first-table-layout","docs\u002Fsetting-up-a-table\u002Fbuilding-your-first-table-layout",{"title":390,"path":391,"stem":392,"order":33},"Importing from The Game Crafter","\u002Fdocs\u002Fsetting-up-a-table\u002Fimporting-from-the-game-crafter","docs\u002Fsetting-up-a-table\u002Fimporting-from-the-game-crafter",{"title":394,"path":395,"stem":396,"order":38},"Importing with manual uploads","\u002Fdocs\u002Fsetting-up-a-table\u002Fimporting-with-manual-uploads","docs\u002Fsetting-up-a-table\u002Fimporting-with-manual-uploads",{"title":398,"path":399,"stem":400,"order":23},"Saving a table configuration","\u002Fdocs\u002Fsetting-up-a-table\u002Fsaving-a-table-configuration","docs\u002Fsetting-up-a-table\u002Fsaving-a-table-configuration",{"id":402,"title":20,"body":403,"description":1877,"extension":1878,"meta":1879,"navigation":1880,"path":21,"seo":1881,"stem":22,"__hash__":1882},"docs\u002Fdocs\u002Fapi\u002Fassets.md",{"type":404,"value":405,"toc":1867},"minimark",[406,410,414,434,438,441,447,548,553,649,654,716,721,794,799,832,836,839,879,882,888,892,906,910,983,987,1055,1059,1082,1086,1099,1103,1106,1110,1131,1135,1268,1272,1385,1389,1400,1404,1411,1415,1436,1444,1448,1470,1474,1482,1489,1493,1496,1863],[407,408,409],"p",{},"The Assets API lets you upload, list, and delete images and other media. Uploads use a three-step presigned URL process. Image derivation (generating optimized display versions) happens automatically when you create components with assets -- you do not need to trigger it yourself.",[411,412,10],"h2",{"id":413},"overview",[415,416,417,421,424,427],"ol",{},[418,419,420],"li",{},"Request a presigned URL from the server",[418,422,423],{},"Upload the file directly to cloud storage using the presigned URL",[418,425,426],{},"Confirm the upload with the server",[418,428,429,430,433],{},"Create components with your assets via the ",[431,432,30],"a",{"href":31}," -- image derivation is handled automatically",[411,435,437],{"id":436},"step-1-request-presigned-url","Step 1: Request Presigned URL",[407,439,440],{},"Request an upload URL for your asset.",[407,442,443],{},[444,445,446],"strong",{},"Request:",[448,449,454],"pre",{"className":450,"code":451,"language":452,"meta":453,"style":453},"language-bash shiki shiki-themes github-light github-dark","POST \u002Fapi\u002Fv1\u002Fgames\u002F:gameId\u002Fassets\u002Fpresign\nAuthorization: Bearer pp_your_token\nContent-Type: application\u002Fjson\n\n{\n  \"fileName\": \"card_back.png\",\n  \"contentType\": \"image\u002Fpng\",\n  \"byteSize\": 15342,\n  \"checksum\": \"sha256-abc123...\"\n}\n","bash","",[455,456,457,469,480,488,494,500,512,522,532,543],"code",{"__ignoreMap":453},[458,459,461,465],"span",{"class":460,"line":28},"line",[458,462,464],{"class":463},"sScJk","POST",[458,466,468],{"class":467},"sZZnC"," \u002Fapi\u002Fv1\u002Fgames\u002F:gameId\u002Fassets\u002Fpresign\n",[458,470,471,474,477],{"class":460,"line":43},[458,472,473],{"class":463},"Authorization:",[458,475,476],{"class":467}," Bearer",[458,478,479],{"class":467}," pp_your_token\n",[458,481,482,485],{"class":460,"line":23},[458,483,484],{"class":463},"Content-Type:",[458,486,487],{"class":467}," application\u002Fjson\n",[458,489,490],{"class":460,"line":33},[458,491,493],{"emptyLinePlaceholder":492},true,"\n",[458,495,496],{"class":460,"line":38},[458,497,499],{"class":498},"sVt8B","{\n",[458,501,502,505,509],{"class":460,"line":327},[458,503,504],{"class":463},"  \"fileName\"",[458,506,508],{"class":507},"sj4cs",":",[458,510,511],{"class":467}," \"card_back.png\",\n",[458,513,514,517,519],{"class":460,"line":18},[458,515,516],{"class":463},"  \"contentType\"",[458,518,508],{"class":507},[458,520,521],{"class":467}," \"image\u002Fpng\",\n",[458,523,524,527,529],{"class":460,"line":340},[458,525,526],{"class":463},"  \"byteSize\"",[458,528,508],{"class":507},[458,530,531],{"class":467}," 15342,\n",[458,533,535,538,540],{"class":460,"line":534},9,[458,536,537],{"class":463},"  \"checksum\"",[458,539,508],{"class":507},[458,541,542],{"class":467}," \"sha256-abc123...\"\n",[458,544,545],{"class":460,"line":314},[458,546,547],{"class":498},"}\n",[407,549,550],{},[444,551,552],{},"Request Body:",[554,555,556,575],"table",{},[557,558,559],"thead",{},[560,561,562,566,569,572],"tr",{},[563,564,565],"th",{},"Field",[563,567,568],{},"Type",[563,570,571],{},"Required",[563,573,574],{},"Description",[576,577,578,595,617,632],"tbody",{},[560,579,580,586,589,592],{},[581,582,583],"td",{},[455,584,585],{},"fileName",[581,587,588],{},"string",[581,590,591],{},"yes",[581,593,594],{},"Original filename (max 256 characters)",[560,596,597,602,604,606],{},[581,598,599],{},[455,600,601],{},"contentType",[581,603,588],{},[581,605,591],{},[581,607,608,609,612,613,616],{},"MIME type (e.g., ",[455,610,611],{},"image\u002Fpng",", ",[455,614,615],{},"image\u002Fjpeg",")",[560,618,619,624,627,629],{},[581,620,621],{},[455,622,623],{},"byteSize",[581,625,626],{},"number",[581,628,591],{},[581,630,631],{},"File size in bytes (max 20 MB)",[560,633,634,639,641,643],{},[581,635,636],{},[455,637,638],{},"checksum",[581,640,588],{},[581,642,591],{},[581,644,645,646],{},"SHA-256 hash of file contents as ",[455,647,648],{},"sha256-BASE64",[407,650,651],{},[444,652,653],{},"Response:",[448,655,659],{"className":656,"code":657,"language":658,"meta":453,"style":453},"language-json shiki shiki-themes github-light github-dark","{\n  \"signedUrl\": \"https:\u002F\u002F...r2.cloudflarestorage.com\u002Fuploads\u002Fsh\u002Fsha256-...\",\n  \"key\": \"uploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\",\n  \"publicUrl\": \"https:\u002F\u002Fpub-....r2.dev\u002Fuploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\",\n  \"contentType\": \"image\u002Fpng\"\n}\n","json",[455,660,661,665,679,691,703,712],{"__ignoreMap":453},[458,662,663],{"class":460,"line":28},[458,664,499],{"class":498},[458,666,667,670,673,676],{"class":460,"line":43},[458,668,669],{"class":507},"  \"signedUrl\"",[458,671,672],{"class":498},": ",[458,674,675],{"class":467},"\"https:\u002F\u002F...r2.cloudflarestorage.com\u002Fuploads\u002Fsh\u002Fsha256-...\"",[458,677,678],{"class":498},",\n",[458,680,681,684,686,689],{"class":460,"line":23},[458,682,683],{"class":507},"  \"key\"",[458,685,672],{"class":498},[458,687,688],{"class":467},"\"uploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\"",[458,690,678],{"class":498},[458,692,693,696,698,701],{"class":460,"line":33},[458,694,695],{"class":507},"  \"publicUrl\"",[458,697,672],{"class":498},[458,699,700],{"class":467},"\"https:\u002F\u002Fpub-....r2.dev\u002Fuploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\"",[458,702,678],{"class":498},[458,704,705,707,709],{"class":460,"line":38},[458,706,516],{"class":507},[458,708,672],{"class":498},[458,710,711],{"class":467},"\"image\u002Fpng\"\n",[458,713,714],{"class":460,"line":327},[458,715,547],{"class":498},[407,717,718],{},[444,719,720],{},"Response Fields:",[554,722,723,733],{},[557,724,725],{},[560,726,727,729,731],{},[563,728,565],{},[563,730,568],{},[563,732,574],{},[576,734,735,747,766,783],{},[560,736,737,742,744],{},[581,738,739],{},[455,740,741],{},"signedUrl",[581,743,588],{},[581,745,746],{},"URL where you PUT the file (valid for 30 minutes)",[560,748,749,754,756],{},[581,750,751],{},[455,752,753],{},"key",[581,755,588],{},[581,757,758,759,762,763,765],{},"Storage key for this asset. Pass to ",[455,760,761],{},"upload-complete"," and to the component's asset ",[455,764,753],{}," field.",[560,767,768,773,775],{},[581,769,770],{},[455,771,772],{},"publicUrl",[581,774,588],{},[581,776,777,778,762,780,765],{},"Public URL of the uploaded file. Pass to ",[455,779,761],{},[455,781,782],{},"sourceUrl",[560,784,785,789,791],{},[581,786,787],{},[455,788,601],{},[581,790,588],{},[581,792,793],{},"The content type you provided",[407,795,796],{},[444,797,798],{},"Errors:",[800,801,802,808,814,820,826],"ul",{},[418,803,804,807],{},[455,805,806],{},"VALIDATION_ERROR",": Missing or invalid metadata",[418,809,810,813],{},[455,811,812],{},"STORAGE_LIMIT_EXCEEDED",": Your account has reached its 2 GB storage quota",[418,815,816,819],{},[455,817,818],{},"RATE_LIMITED",": Upload rate limit exceeded",[418,821,822,825],{},[455,823,824],{},"GAME_NOT_FOUND",": The game ID does not exist",[418,827,828,831],{},[455,829,830],{},"PERMISSION_DENIED",": You do not own this game",[411,833,835],{"id":834},"step-2-upload-file","Step 2: Upload File",[407,837,838],{},"Upload your file directly to the presigned URL using a PUT request:",[448,840,842],{"className":450,"code":841,"language":452,"meta":453,"style":453},"curl -X PUT \"SIGNED_URL\" \\\n  -H \"Content-Type: image\u002Fpng\" \\\n  --data-binary @card_back.png\n",[455,843,844,861,871],{"__ignoreMap":453},[458,845,846,849,852,855,858],{"class":460,"line":28},[458,847,848],{"class":463},"curl",[458,850,851],{"class":507}," -X",[458,853,854],{"class":467}," PUT",[458,856,857],{"class":467}," \"SIGNED_URL\"",[458,859,860],{"class":507}," \\\n",[458,862,863,866,869],{"class":460,"line":43},[458,864,865],{"class":507},"  -H",[458,867,868],{"class":467}," \"Content-Type: image\u002Fpng\"",[458,870,860],{"class":507},[458,872,873,876],{"class":460,"line":23},[458,874,875],{"class":507},"  --data-binary",[458,877,878],{"class":467}," @card_back.png\n",[407,880,881],{},"The presigned URL is valid for 30 minutes. If it expires, request a new presigned URL.",[407,883,884,887],{},[444,885,886],{},"Expected Response:"," HTTP 200 OK (exact response depends on cloud storage provider)",[411,889,891],{"id":890},"step-3-confirm-upload","Step 3: Confirm Upload",[407,893,894,895,612,897,899,900,902,903,905],{},"After the file is successfully uploaded, confirm it with the server. Use the ",[455,896,753],{},[455,898,772],{},", and ",[455,901,601],{}," from the presign response plus the original ",[455,904,623],{},".",[407,907,908],{},[444,909,446],{},[448,911,913],{"className":450,"code":912,"language":452,"meta":453,"style":453},"POST \u002Fapi\u002Fv1\u002Fgames\u002F:gameId\u002Fassets\u002Fupload-complete\nAuthorization: Bearer pp_your_token\nContent-Type: application\u002Fjson\n\n{\n  \"key\": \"uploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\",\n  \"publicUrl\": \"https:\u002F\u002Fpub-....r2.dev\u002Fuploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\",\n  \"byteSize\": 15342,\n  \"contentType\": \"image\u002Fpng\"\n}\n",[455,914,915,922,930,936,940,944,953,962,970,979],{"__ignoreMap":453},[458,916,917,919],{"class":460,"line":28},[458,918,464],{"class":463},[458,920,921],{"class":467}," \u002Fapi\u002Fv1\u002Fgames\u002F:gameId\u002Fassets\u002Fupload-complete\n",[458,923,924,926,928],{"class":460,"line":43},[458,925,473],{"class":463},[458,927,476],{"class":467},[458,929,479],{"class":467},[458,931,932,934],{"class":460,"line":23},[458,933,484],{"class":463},[458,935,487],{"class":467},[458,937,938],{"class":460,"line":33},[458,939,493],{"emptyLinePlaceholder":492},[458,941,942],{"class":460,"line":38},[458,943,499],{"class":498},[458,945,946,948,950],{"class":460,"line":327},[458,947,683],{"class":463},[458,949,508],{"class":507},[458,951,952],{"class":467}," \"uploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\",\n",[458,954,955,957,959],{"class":460,"line":18},[458,956,695],{"class":463},[458,958,508],{"class":507},[458,960,961],{"class":467}," \"https:\u002F\u002Fpub-....r2.dev\u002Fuploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\",\n",[458,963,964,966,968],{"class":460,"line":340},[458,965,526],{"class":463},[458,967,508],{"class":507},[458,969,531],{"class":467},[458,971,972,974,976],{"class":460,"line":534},[458,973,516],{"class":463},[458,975,508],{"class":507},[458,977,978],{"class":467}," \"image\u002Fpng\"\n",[458,980,981],{"class":460,"line":314},[458,982,547],{"class":498},[407,984,985],{},[444,986,552],{},[554,988,989,1001],{},[557,990,991],{},[560,992,993,995,997,999],{},[563,994,565],{},[563,996,568],{},[563,998,571],{},[563,1000,574],{},[576,1002,1003,1016,1029,1042],{},[560,1004,1005,1009,1011,1013],{},[581,1006,1007],{},[455,1008,753],{},[581,1010,588],{},[581,1012,591],{},[581,1014,1015],{},"The storage key from the presign response",[560,1017,1018,1022,1024,1026],{},[581,1019,1020],{},[455,1021,772],{},[581,1023,588],{},[581,1025,591],{},[581,1027,1028],{},"The public URL from the presign response",[560,1030,1031,1035,1037,1039],{},[581,1032,1033],{},[455,1034,623],{},[581,1036,626],{},[581,1038,591],{},[581,1040,1041],{},"File size in bytes (must match the original presign request)",[560,1043,1044,1048,1050,1052],{},[581,1045,1046],{},[455,1047,601],{},[581,1049,588],{},[581,1051,591],{},[581,1053,1054],{},"MIME type (must match the original presign request)",[407,1056,1057],{},[444,1058,653],{},[448,1060,1062],{"className":656,"code":1061,"language":658,"meta":453,"style":453},"{\n  \"ok\": true\n}\n",[455,1063,1064,1068,1078],{"__ignoreMap":453},[458,1065,1066],{"class":460,"line":28},[458,1067,499],{"class":498},[458,1069,1070,1073,1075],{"class":460,"line":43},[458,1071,1072],{"class":507},"  \"ok\"",[458,1074,672],{"class":498},[458,1076,1077],{"class":507},"true\n",[458,1079,1080],{"class":460,"line":23},[458,1081,547],{"class":498},[407,1083,1084],{},[444,1085,798],{},[800,1087,1088,1093],{},[418,1089,1090,1092],{},[455,1091,806],{},": Missing or invalid fields",[418,1094,1095,1098],{},[455,1096,1097],{},"UNAUTHORIZED",": Your token is invalid",[411,1100,1102],{"id":1101},"list-assets","List Assets",[407,1104,1105],{},"Retrieve all assets your app has uploaded for a game. Useful for deduplication (skip uploading assets that already exist) and cleanup.",[407,1107,1108],{},[444,1109,446],{},[448,1111,1113],{"className":450,"code":1112,"language":452,"meta":453,"style":453},"GET \u002Fapi\u002Fv1\u002Fgames\u002F:gameId\u002Fassets\nAuthorization: Bearer pp_your_token\n",[455,1114,1115,1123],{"__ignoreMap":453},[458,1116,1117,1120],{"class":460,"line":28},[458,1118,1119],{"class":463},"GET",[458,1121,1122],{"class":467}," \u002Fapi\u002Fv1\u002Fgames\u002F:gameId\u002Fassets\n",[458,1124,1125,1127,1129],{"class":460,"line":43},[458,1126,473],{"class":463},[458,1128,476],{"class":467},[458,1130,479],{"class":467},[407,1132,1133],{},[444,1134,653],{},[448,1136,1138],{"className":656,"code":1137,"language":658,"meta":453,"style":453},"{\n  \"assets\": [\n    {\n      \"id\": \"a1b2...\",\n      \"componentId\": \"j57a...\",\n      \"kind\": \"image\",\n      \"sourceUrl\": \"https:\u002F\u002Fpub-....r2.dev\u002Fuploads\u002Fsh\u002Fsha256-RGXC3ce7w3...\",\n      \"mimeType\": \"image\u002Fpng\",\n      \"widthPx\": 750,\n      \"heightPx\": 1050,\n      \"createdAt\": 1713800000000\n    }\n  ]\n}\n",[455,1139,1140,1144,1152,1157,1169,1181,1193,1204,1216,1228,1240,1251,1257,1263],{"__ignoreMap":453},[458,1141,1142],{"class":460,"line":28},[458,1143,499],{"class":498},[458,1145,1146,1149],{"class":460,"line":43},[458,1147,1148],{"class":507},"  \"assets\"",[458,1150,1151],{"class":498},": [\n",[458,1153,1154],{"class":460,"line":23},[458,1155,1156],{"class":498},"    {\n",[458,1158,1159,1162,1164,1167],{"class":460,"line":33},[458,1160,1161],{"class":507},"      \"id\"",[458,1163,672],{"class":498},[458,1165,1166],{"class":467},"\"a1b2...\"",[458,1168,678],{"class":498},[458,1170,1171,1174,1176,1179],{"class":460,"line":38},[458,1172,1173],{"class":507},"      \"componentId\"",[458,1175,672],{"class":498},[458,1177,1178],{"class":467},"\"j57a...\"",[458,1180,678],{"class":498},[458,1182,1183,1186,1188,1191],{"class":460,"line":327},[458,1184,1185],{"class":507},"      \"kind\"",[458,1187,672],{"class":498},[458,1189,1190],{"class":467},"\"image\"",[458,1192,678],{"class":498},[458,1194,1195,1198,1200,1202],{"class":460,"line":18},[458,1196,1197],{"class":507},"      \"sourceUrl\"",[458,1199,672],{"class":498},[458,1201,700],{"class":467},[458,1203,678],{"class":498},[458,1205,1206,1209,1211,1214],{"class":460,"line":340},[458,1207,1208],{"class":507},"      \"mimeType\"",[458,1210,672],{"class":498},[458,1212,1213],{"class":467},"\"image\u002Fpng\"",[458,1215,678],{"class":498},[458,1217,1218,1221,1223,1226],{"class":460,"line":534},[458,1219,1220],{"class":507},"      \"widthPx\"",[458,1222,672],{"class":498},[458,1224,1225],{"class":507},"750",[458,1227,678],{"class":498},[458,1229,1230,1233,1235,1238],{"class":460,"line":314},[458,1231,1232],{"class":507},"      \"heightPx\"",[458,1234,672],{"class":498},[458,1236,1237],{"class":507},"1050",[458,1239,678],{"class":498},[458,1241,1243,1246,1248],{"class":460,"line":1242},11,[458,1244,1245],{"class":507},"      \"createdAt\"",[458,1247,672],{"class":498},[458,1249,1250],{"class":507},"1713800000000\n",[458,1252,1254],{"class":460,"line":1253},12,[458,1255,1256],{"class":498},"    }\n",[458,1258,1260],{"class":460,"line":1259},13,[458,1261,1262],{"class":498},"  ]\n",[458,1264,1266],{"class":460,"line":1265},14,[458,1267,547],{"class":498},[407,1269,1270],{},[444,1271,720],{},[554,1273,1274,1284],{},[557,1275,1276],{},[560,1277,1278,1280,1282],{},[563,1279,565],{},[563,1281,568],{},[563,1283,574],{},[576,1285,1286,1298,1311,1326,1337,1349,1361,1373],{},[560,1287,1288,1293,1295],{},[581,1289,1290],{},[455,1291,1292],{},"id",[581,1294,588],{},[581,1296,1297],{},"Unique asset identifier",[560,1299,1300,1305,1308],{},[581,1301,1302],{},[455,1303,1304],{},"componentId",[581,1306,1307],{},"string or null",[581,1309,1310],{},"The component this asset belongs to",[560,1312,1313,1318,1320],{},[581,1314,1315],{},[455,1316,1317],{},"kind",[581,1319,588],{},[581,1321,1322,1323,616],{},"Asset type (e.g., ",[455,1324,1325],{},"image",[560,1327,1328,1332,1334],{},[581,1329,1330],{},[455,1331,782],{},[581,1333,588],{},[581,1335,1336],{},"Public URL of the uploaded file",[560,1338,1339,1344,1346],{},[581,1340,1341],{},[455,1342,1343],{},"mimeType",[581,1345,588],{},[581,1347,1348],{},"MIME type of the file",[560,1350,1351,1356,1358],{},[581,1352,1353],{},[455,1354,1355],{},"widthPx",[581,1357,626],{},[581,1359,1360],{},"Image width in pixels",[560,1362,1363,1368,1370],{},[581,1364,1365],{},[455,1366,1367],{},"heightPx",[581,1369,626],{},[581,1371,1372],{},"Image height in pixels",[560,1374,1375,1380,1382],{},[581,1376,1377],{},[455,1378,1379],{},"createdAt",[581,1381,626],{},[581,1383,1384],{},"Creation timestamp (milliseconds)",[407,1386,1387],{},[444,1388,798],{},[800,1390,1391,1396],{},[418,1392,1393,1395],{},[455,1394,824],{},": The game does not exist",[418,1397,1398,831],{},[455,1399,830],{},[411,1401,1403],{"id":1402},"delete-asset","Delete Asset",[407,1405,1406,1407,1410],{},"Delete a single asset and its derived versions. If the asset is attached to a component, the reference is automatically removed from that component's ",[455,1408,1409],{},"payload.imageFaces",". Only works on assets in a draft revision.",[407,1412,1413],{},[444,1414,446],{},[448,1416,1418],{"className":450,"code":1417,"language":452,"meta":453,"style":453},"DELETE \u002Fapi\u002Fv1\u002Fgames\u002F:gameId\u002Fassets\u002F:assetId\nAuthorization: Bearer pp_your_token\n",[455,1419,1420,1428],{"__ignoreMap":453},[458,1421,1422,1425],{"class":460,"line":28},[458,1423,1424],{"class":463},"DELETE",[458,1426,1427],{"class":467}," \u002Fapi\u002Fv1\u002Fgames\u002F:gameId\u002Fassets\u002F:assetId\n",[458,1429,1430,1432,1434],{"class":460,"line":43},[458,1431,473],{"class":463},[458,1433,476],{"class":467},[458,1435,479],{"class":467},[407,1437,1438,1440,1441],{},[444,1439,653],{}," ",[455,1442,1443],{},"204 No Content",[407,1445,1446],{},[444,1447,798],{},[800,1449,1450,1456,1462,1466],{},[418,1451,1452,1455],{},[455,1453,1454],{},"ASSET_NOT_FOUND",": The asset does not exist or belongs to a different app",[418,1457,1458,1461],{},[455,1459,1460],{},"REVISION_FINALIZED",": The asset belongs to a finalized revision and cannot be deleted",[418,1463,1464,1395],{},[455,1465,824],{},[418,1467,1468,831],{},[455,1469,830],{},[411,1471,1473],{"id":1472},"rate-limits","Rate Limits",[800,1475,1476,1479],{},[418,1477,1478],{},"Presign requests: 60 per minute",[418,1480,1481],{},"Upload completion: 60 per minute",[407,1483,1484,1485,1488],{},"See ",[431,1486,1487],{"href":36},"Errors"," for all rate limits.",[411,1490,1492],{"id":1491},"typical-workflow","Typical Workflow",[407,1494,1495],{},"Here is the complete workflow for uploading assets and creating components:",[448,1497,1501],{"className":1498,"code":1499,"language":1500,"meta":453,"style":453},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F 1. Get presigned URL\nconst presignResponse = await fetch(\n  `https:\u002F\u002Fplaytestparlor.com\u002Fapi\u002Fv1\u002Fgames\u002F${gameId}\u002Fassets\u002Fpresign`,\n  {\n    method: \"POST\",\n    headers: {\n      \"Authorization\": `Bearer ${token}`,\n      \"Content-Type\": \"application\u002Fjson\"\n    },\n    body: JSON.stringify({\n      fileName: \"card.png\",\n      contentType: \"image\u002Fpng\",\n      byteSize: fileSize,\n      checksum: `sha256-${base64Hash}`\n    })\n  }\n);\nconst { signedUrl, key, publicUrl, contentType } =\n  await presignResponse.json();\n\n\u002F\u002F 2. Upload file to presigned URL\nawait fetch(signedUrl, {\n  method: \"PUT\",\n  headers: { \"Content-Type\": contentType },\n  body: fileBlob\n});\n\n\u002F\u002F 3. Confirm upload\nawait fetch(\n  `https:\u002F\u002Fplaytestparlor.com\u002Fapi\u002Fv1\u002Fgames\u002F${gameId}\u002Fassets\u002Fupload-complete`,\n  {\n    method: \"POST\",\n    headers: {\n      \"Authorization\": `Bearer ${token}`,\n      \"Content-Type\": \"application\u002Fjson\"\n    },\n    body: JSON.stringify({ key, publicUrl, byteSize: fileSize, contentType })\n  }\n);\n\n\u002F\u002F 4. Create component with asset -- derivation happens automatically\nawait fetch(\n  `https:\u002F\u002Fplaytestparlor.com\u002Fapi\u002Fv1\u002Fgames\u002F${gameId}\u002Fcomponents`,\n  {\n    method: \"POST\",\n    headers: {\n      \"Authorization\": `Bearer ${token}`,\n      \"Content-Type\": \"application\u002Fjson\"\n    },\n    body: JSON.stringify({\n      kind: \"tile\",\n      name: \"My Card\",\n      externalKey: \"my-card-001\",\n      widthMm: 63.5,\n      heightMm: 88.9,\n      assets: [{\n        sideKey: \"front\",\n        key,\n        sourceUrl: publicUrl,\n        contentType,\n        widthPx: 750,\n        heightPx: 1050\n      }]\n    })\n  }\n);\n","javascript",[455,1502,1503,1508,1513,1518,1523,1528,1533,1538,1543,1548,1553,1558,1563,1568,1573,1579,1585,1591,1597,1603,1608,1614,1620,1626,1632,1638,1644,1649,1655,1661,1667,1672,1677,1682,1687,1692,1697,1703,1708,1713,1718,1724,1729,1735,1740,1745,1750,1755,1760,1765,1770,1776,1782,1788,1794,1800,1806,1812,1818,1824,1830,1836,1842,1848,1853,1858],{"__ignoreMap":453},[458,1504,1505],{"class":460,"line":28},[458,1506,1507],{},"\u002F\u002F 1. Get presigned URL\n",[458,1509,1510],{"class":460,"line":43},[458,1511,1512],{},"const presignResponse = await fetch(\n",[458,1514,1515],{"class":460,"line":23},[458,1516,1517],{},"  `https:\u002F\u002Fplaytestparlor.com\u002Fapi\u002Fv1\u002Fgames\u002F${gameId}\u002Fassets\u002Fpresign`,\n",[458,1519,1520],{"class":460,"line":33},[458,1521,1522],{},"  {\n",[458,1524,1525],{"class":460,"line":38},[458,1526,1527],{},"    method: \"POST\",\n",[458,1529,1530],{"class":460,"line":327},[458,1531,1532],{},"    headers: {\n",[458,1534,1535],{"class":460,"line":18},[458,1536,1537],{},"      \"Authorization\": `Bearer ${token}`,\n",[458,1539,1540],{"class":460,"line":340},[458,1541,1542],{},"      \"Content-Type\": \"application\u002Fjson\"\n",[458,1544,1545],{"class":460,"line":534},[458,1546,1547],{},"    },\n",[458,1549,1550],{"class":460,"line":314},[458,1551,1552],{},"    body: JSON.stringify({\n",[458,1554,1555],{"class":460,"line":1242},[458,1556,1557],{},"      fileName: \"card.png\",\n",[458,1559,1560],{"class":460,"line":1253},[458,1561,1562],{},"      contentType: \"image\u002Fpng\",\n",[458,1564,1565],{"class":460,"line":1259},[458,1566,1567],{},"      byteSize: fileSize,\n",[458,1569,1570],{"class":460,"line":1265},[458,1571,1572],{},"      checksum: `sha256-${base64Hash}`\n",[458,1574,1576],{"class":460,"line":1575},15,[458,1577,1578],{},"    })\n",[458,1580,1582],{"class":460,"line":1581},16,[458,1583,1584],{},"  }\n",[458,1586,1588],{"class":460,"line":1587},17,[458,1589,1590],{},");\n",[458,1592,1594],{"class":460,"line":1593},18,[458,1595,1596],{},"const { signedUrl, key, publicUrl, contentType } =\n",[458,1598,1600],{"class":460,"line":1599},19,[458,1601,1602],{},"  await presignResponse.json();\n",[458,1604,1606],{"class":460,"line":1605},20,[458,1607,493],{"emptyLinePlaceholder":492},[458,1609,1611],{"class":460,"line":1610},21,[458,1612,1613],{},"\u002F\u002F 2. Upload file to presigned URL\n",[458,1615,1617],{"class":460,"line":1616},22,[458,1618,1619],{},"await fetch(signedUrl, {\n",[458,1621,1623],{"class":460,"line":1622},23,[458,1624,1625],{},"  method: \"PUT\",\n",[458,1627,1629],{"class":460,"line":1628},24,[458,1630,1631],{},"  headers: { \"Content-Type\": contentType },\n",[458,1633,1635],{"class":460,"line":1634},25,[458,1636,1637],{},"  body: fileBlob\n",[458,1639,1641],{"class":460,"line":1640},26,[458,1642,1643],{},"});\n",[458,1645,1647],{"class":460,"line":1646},27,[458,1648,493],{"emptyLinePlaceholder":492},[458,1650,1652],{"class":460,"line":1651},28,[458,1653,1654],{},"\u002F\u002F 3. Confirm upload\n",[458,1656,1658],{"class":460,"line":1657},29,[458,1659,1660],{},"await fetch(\n",[458,1662,1664],{"class":460,"line":1663},30,[458,1665,1666],{},"  `https:\u002F\u002Fplaytestparlor.com\u002Fapi\u002Fv1\u002Fgames\u002F${gameId}\u002Fassets\u002Fupload-complete`,\n",[458,1668,1670],{"class":460,"line":1669},31,[458,1671,1522],{},[458,1673,1675],{"class":460,"line":1674},32,[458,1676,1527],{},[458,1678,1680],{"class":460,"line":1679},33,[458,1681,1532],{},[458,1683,1685],{"class":460,"line":1684},34,[458,1686,1537],{},[458,1688,1690],{"class":460,"line":1689},35,[458,1691,1542],{},[458,1693,1695],{"class":460,"line":1694},36,[458,1696,1547],{},[458,1698,1700],{"class":460,"line":1699},37,[458,1701,1702],{},"    body: JSON.stringify({ key, publicUrl, byteSize: fileSize, contentType })\n",[458,1704,1706],{"class":460,"line":1705},38,[458,1707,1584],{},[458,1709,1711],{"class":460,"line":1710},39,[458,1712,1590],{},[458,1714,1716],{"class":460,"line":1715},40,[458,1717,493],{"emptyLinePlaceholder":492},[458,1719,1721],{"class":460,"line":1720},41,[458,1722,1723],{},"\u002F\u002F 4. Create component with asset -- derivation happens automatically\n",[458,1725,1727],{"class":460,"line":1726},42,[458,1728,1660],{},[458,1730,1732],{"class":460,"line":1731},43,[458,1733,1734],{},"  `https:\u002F\u002Fplaytestparlor.com\u002Fapi\u002Fv1\u002Fgames\u002F${gameId}\u002Fcomponents`,\n",[458,1736,1738],{"class":460,"line":1737},44,[458,1739,1522],{},[458,1741,1743],{"class":460,"line":1742},45,[458,1744,1527],{},[458,1746,1748],{"class":460,"line":1747},46,[458,1749,1532],{},[458,1751,1753],{"class":460,"line":1752},47,[458,1754,1537],{},[458,1756,1758],{"class":460,"line":1757},48,[458,1759,1542],{},[458,1761,1763],{"class":460,"line":1762},49,[458,1764,1547],{},[458,1766,1768],{"class":460,"line":1767},50,[458,1769,1552],{},[458,1771,1773],{"class":460,"line":1772},51,[458,1774,1775],{},"      kind: \"tile\",\n",[458,1777,1779],{"class":460,"line":1778},52,[458,1780,1781],{},"      name: \"My Card\",\n",[458,1783,1785],{"class":460,"line":1784},53,[458,1786,1787],{},"      externalKey: \"my-card-001\",\n",[458,1789,1791],{"class":460,"line":1790},54,[458,1792,1793],{},"      widthMm: 63.5,\n",[458,1795,1797],{"class":460,"line":1796},55,[458,1798,1799],{},"      heightMm: 88.9,\n",[458,1801,1803],{"class":460,"line":1802},56,[458,1804,1805],{},"      assets: [{\n",[458,1807,1809],{"class":460,"line":1808},57,[458,1810,1811],{},"        sideKey: \"front\",\n",[458,1813,1815],{"class":460,"line":1814},58,[458,1816,1817],{},"        key,\n",[458,1819,1821],{"class":460,"line":1820},59,[458,1822,1823],{},"        sourceUrl: publicUrl,\n",[458,1825,1827],{"class":460,"line":1826},60,[458,1828,1829],{},"        contentType,\n",[458,1831,1833],{"class":460,"line":1832},61,[458,1834,1835],{},"        widthPx: 750,\n",[458,1837,1839],{"class":460,"line":1838},62,[458,1840,1841],{},"        heightPx: 1050\n",[458,1843,1845],{"class":460,"line":1844},63,[458,1846,1847],{},"      }]\n",[458,1849,1851],{"class":460,"line":1850},64,[458,1852,1578],{},[458,1854,1856],{"class":460,"line":1855},65,[458,1857,1584],{},[458,1859,1861],{"class":460,"line":1860},66,[458,1862,1590],{},[1864,1865,1866],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":453,"searchDepth":43,"depth":43,"links":1868},[1869,1870,1871,1872,1873,1874,1875,1876],{"id":413,"depth":43,"text":10},{"id":436,"depth":43,"text":437},{"id":834,"depth":43,"text":835},{"id":890,"depth":43,"text":891},{"id":1101,"depth":43,"text":1102},{"id":1402,"depth":43,"text":1403},{"id":1472,"depth":43,"text":1473},{"id":1491,"depth":43,"text":1492},"Upload, list, and delete images and media in Playtest Parlor.","md",{},{"order":23},{"title":20,"description":1877},"lMwwjmHj7rwX-rimlv3IJKbx3kv1sb0LpOmGSz7iDag",1778263810617]