MOTHv3 API ========== MOTH, by design, uses a small number of API endpoints. Whenever possible, we decided to push complexity into the client, keeping the server as simple as we could make it. After all, this is a hacking contest. If a participant finds a vulnerability in code running on their own machine, the people running the server don't care. Specification ============= You make requests as HTTP GET query arguments: https://server/path/elements/api/v3/endpoint?var1=val1&var2=val2 The server returns a [JSend](https://labs.omniti.com/labs/jsend) response: { "status": "success", "data": "Any JS data type here" } Client State ============ The client (or user interacting with the client) needs to remember only one thing: * teamId: the team ID used to register A naive client, like the one we used from 2009-2018, can ask the user to type in the team ID for every submission. This is fine. Endpoints ========= RegisterTeam(teamId, teamName) ------------------------------- Register a team name with a team hash. ### Parameters * teamId: Team's unique identifier (usually a hex value) * teamName: Team's human-readable name On success, no data is returned. On failure, message contains an English explanation of why. ### Example https://server/api/v3/RegisterTeam?teamId=8b1292ca&teamName=Lexical+Pedants { "status": "success", "data": null } GetState() ---------- Return all current state of the puzzle server. ### Parameters None ### Return data * puzzles: dictionary mapping from category to one of the following: * list of point values currently open * URL to puzzle root (intended for token-based puzzles) * teams: mapping from anonymized team ID to team name * log: list of (timestamp, team number, category, points) * notices: list of HTML broadcast notices to display to the user * now: current server time (unix epoch) ### Example https://server/api/v3/GetState { "status": "success", "data": { "puzzles": { "sequence": [1, 2], "codebreaking": [10], "wopr": "https://appspot.com/dooted-bagel-8372/entry" }, "teams": { "0": "Zelda", "1": "Defender" }, "log": [ [1526478368, "0", "sequence", 1], [1526478524, "1", "sequence", 1], [1526478536, "0", "nocode", 1] ], "notices": [ "WOPR category is now open", "Event closes at 18:00 today, and will resume tomorrow at 08:00" ], "now": 1527170088 } } GetPuzzle(category, points) -------------------- Return a puzzle. ### Parameters * category: name of category to fetch from * points: point value of the puzzle to fetch ### Return data * authors: List of puzzle authors * hashes: list of djbhash values of acceptable answers * files: dictionary of puzzle-associated filenames and their URLs * body: HTML body of the puzzle ### Example https://server/api/v3/GetPuzzle?category=sequence&points=1 { "status": "success", "data": { "authors": ["neale"], "hashes": [177627], "files": { "happy.png": "https://cdn/assets/0904cf3a437a348bea2c49d56a3087c26a01a63c.png" }, "body": "
1 2 3 4 5 _\n
\n" } SubmitAnswer(teamId, category, points, answer) ---------------------- Submit an answer to a puzzle. ### Parameters * teamId: Team ID (optional: if ommitted, answer is verified but no points are awarded) * category: category name of puzzle * points: point value of puzzle * answer: attempted answer ### Return Data * epilog: HTML to display upon successfully answering the puzzle ### Example https://server/api/v3/SubmitAnswer?teamId=8b1292ca&category=sequence&points=1&answer=6 { "status": "success", "data": { "epilog": "That's right: in base 10, 5 + 1 = 6." } } SubmitToken(teamId, token) --------------------- Submit a token for points ### Parameters * teamId: Team ID * token: Token being submitted ### Return data * category: category for which this token awarded points * points: number of points awarded * epilog: HTML to display upon successfully answering the puzzle ### Example https://server/api/v3/SubmitToken?teamId=8b1292ca&token=wat:30:xylep-radar-nanox { "status": "success", "data": { "category": "wat", "points": 30, "epilog": "" } }