{"openapi":"3.1.0","info":{"title":"ReadyRef Play Maker","version":"1.0.0","description":"Draw flag football plays from names (formation, routes, ball path, defense), check them against IFAF rules, simulate them, and get a link the coach can open. Read /api/reference first. The same tools are available over MCP at https://readyref.app/mcp."},"servers":[{"url":"https://readyref.app/mcp"}],"paths":{"/api/reference":{"get":{"operationId":"playmakerReference","summary":"The Play Maker reference","description":"Read this first. Formats, positions, coordinate conventions, formations with player spots, the named route library with parameters, ball path options, library defenses, rulesets and what they check, limits and an example spec. Static; read it once per conversation.","responses":{"200":{"description":"The reference","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/check":{"post":{"operationId":"checkPlay","summary":"Check plays","description":"Build and check plays without saving anything: returns the exact plays as stored, every change and error, IFAF rule checks with rule numbers, and a rough simulation against defenses (as drawn and with the QB reading). Use it to iterate; fix errors before create_play_draft.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plays":{"type":"array","items":{"type":"object","description":"One play. Names first (formation, route names); coordinates only where needed. See playmaker_reference.","properties":{"format":{"type":"string","enum":["4v4","5v5","nfl5","6v6","7v7","8v8","9v9"],"description":"Default 5v5. nfl5 = NFL FLAG 5v5."},"name":{"type":"string","maxLength":40},"note":{"type":"string","maxLength":80},"situation":{"type":"object","properties":{"goal":{"type":"integer","enum":[0,5,10,15,20],"description":"Yards to the goal line (0 = not shown; 5 = no-run zone)."},"mid":{"type":"integer","enum":[0,5,10,15,20],"description":"NFL FLAG (nfl5) only, instead of goal: yards to midfield (5 = its no-run zone)."},"down":{"type":"integer","minimum":1,"maximum":4},"toGo":{"type":"number","minimum":1,"maximum":30}}},"formation":{"type":"object","description":"A named formation for the format (playmaker_reference formats.<f>.formations), drawn strong right unless strong: \"left\".","properties":{"id":{"type":"string"},"strong":{"type":"string","enum":["left","right"]}},"required":["id"]},"players":{"type":"array","description":"Instead of a formation: your own spots. x across from the left sideline, y from the line (-1 = on the line).","items":{"type":"object","properties":{"pos":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"label":{"type":"string","maxLength":2}},"required":["pos","x","y"]}},"routes":{"type":"object","description":"By position letter. Named: { \"route\": \"corner\", \"depth\": 10 } (depth = yards past the line where it breaks; width = yards across). Custom: { \"points\": [[dx, dy], ...] } offsets from where he is set.","additionalProperties":{"type":"object","properties":{"route":{"type":"string"},"depth":{"type":"number"},"width":{"type":"number"},"side":{"type":"string","enum":["left","right"]},"points":{"type":"array","items":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2},"maxItems":12},"kind":{"type":"string","enum":["route","motion","block"]},"smooth":{"type":"boolean"},"cue":{"type":"string","maxLength":60,"description":"The player's callout on the play sheet."}}}},"motion":{"type":"object","description":"Pre-snap motion by position letter: { \"to\": [x, y] } where he sets (absolute), or \"points\" (offsets). live: true = still moving at the snap.","additionalProperties":{"type":"object","properties":{"to":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2},"points":{"type":"array","items":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2},"maxItems":8},"live":{"type":"boolean"},"smooth":{"type":"boolean"}}}},"ball":{"type":"object","description":"pass | reads | handoff | pitch, chained with \"then\". See playmaker_reference.ball.","properties":{"type":{"type":"string","enum":["pass","reads","handoff","pitch"]},"to":{"type":"string"},"at":{"type":"string","enum":["end","set","wp"]},"wp":{"type":"integer","minimum":0},"from":{"type":"string"},"quick":{"type":"boolean"},"then":{"type":"object"}}},"defense":{"type":"object","description":"{ \"library\": \"<slug>\" } or { \"defenders\": [...] } (man coverage by position letter).","properties":{"library":{"type":"string"},"defenders":{"type":"array","items":{"type":"object"}}}},"side":{"type":"string","enum":["offense","defense"]},"ruleset":{"type":"string","enum":["ifaf-2023","league-6v6","nfl-flag","league"],"description":"Default: ifaf-2023 for 5v5 and 7v7, nfl-flag for nfl5, league-6v6 for 6v6, league for 4v4, 8v8 and 9v9."}}},"minItems":1,"maxItems":8,"description":"1 to 8 plays (a scenario: the same offense against two defenses is two plays)."},"name":{"type":"string","maxLength":40,"description":"A name for the set of plays (defaults to the first play's name)."},"allowAdjustments":{"type":"boolean","description":"Accept changes needed to fit the field (then tell the coach). Default false: they are errors."}},"required":["plays"]}}}},"responses":{"200":{"description":"Checked (and, for draft, stored)","content":{"application/json":{"schema":{"type":"object","description":"ok, plays (exactly as stored), contentHash, changes, issues, rules, analysis, analysisPartial, caveat, assistantNotes; create also has draft { id, url, previewUrl, expiresAt, reused }."}}}},"422":{"description":"The plays have errors; nothing stored. Fix them and send again.","content":{"application/json":{"schema":{"type":"object","description":"ok, plays (exactly as stored), contentHash, changes, issues, rules, analysis, analysisPartial, caveat, assistantNotes; create also has draft { id, url, previewUrl, expiresAt, reused }."}}}},"429":{"description":"A limit was reached; try later."},"503":{"description":"Temporarily unavailable."}}}},"/api/draft":{"post":{"operationId":"createPlayDraft","summary":"Make a play link","description":"Check the plays and, if there are no errors, store them as a private draft and return its link (readyref.app/draft/...), a preview image and the same report. The coach can watch it run, save it to ReadyRef or edit it in the free Play Maker; it expires in 7 days. Rule fails don't block a draft: tell the coach about them. Always give the coach the link.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plays":{"type":"array","items":{"type":"object","description":"One play. Names first (formation, route names); coordinates only where needed. See playmaker_reference.","properties":{"format":{"type":"string","enum":["4v4","5v5","nfl5","6v6","7v7","8v8","9v9"],"description":"Default 5v5. nfl5 = NFL FLAG 5v5."},"name":{"type":"string","maxLength":40},"note":{"type":"string","maxLength":80},"situation":{"type":"object","properties":{"goal":{"type":"integer","enum":[0,5,10,15,20],"description":"Yards to the goal line (0 = not shown; 5 = no-run zone)."},"mid":{"type":"integer","enum":[0,5,10,15,20],"description":"NFL FLAG (nfl5) only, instead of goal: yards to midfield (5 = its no-run zone)."},"down":{"type":"integer","minimum":1,"maximum":4},"toGo":{"type":"number","minimum":1,"maximum":30}}},"formation":{"type":"object","description":"A named formation for the format (playmaker_reference formats.<f>.formations), drawn strong right unless strong: \"left\".","properties":{"id":{"type":"string"},"strong":{"type":"string","enum":["left","right"]}},"required":["id"]},"players":{"type":"array","description":"Instead of a formation: your own spots. x across from the left sideline, y from the line (-1 = on the line).","items":{"type":"object","properties":{"pos":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"label":{"type":"string","maxLength":2}},"required":["pos","x","y"]}},"routes":{"type":"object","description":"By position letter. Named: { \"route\": \"corner\", \"depth\": 10 } (depth = yards past the line where it breaks; width = yards across). Custom: { \"points\": [[dx, dy], ...] } offsets from where he is set.","additionalProperties":{"type":"object","properties":{"route":{"type":"string"},"depth":{"type":"number"},"width":{"type":"number"},"side":{"type":"string","enum":["left","right"]},"points":{"type":"array","items":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2},"maxItems":12},"kind":{"type":"string","enum":["route","motion","block"]},"smooth":{"type":"boolean"},"cue":{"type":"string","maxLength":60,"description":"The player's callout on the play sheet."}}}},"motion":{"type":"object","description":"Pre-snap motion by position letter: { \"to\": [x, y] } where he sets (absolute), or \"points\" (offsets). live: true = still moving at the snap.","additionalProperties":{"type":"object","properties":{"to":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2},"points":{"type":"array","items":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2},"maxItems":8},"live":{"type":"boolean"},"smooth":{"type":"boolean"}}}},"ball":{"type":"object","description":"pass | reads | handoff | pitch, chained with \"then\". See playmaker_reference.ball.","properties":{"type":{"type":"string","enum":["pass","reads","handoff","pitch"]},"to":{"type":"string"},"at":{"type":"string","enum":["end","set","wp"]},"wp":{"type":"integer","minimum":0},"from":{"type":"string"},"quick":{"type":"boolean"},"then":{"type":"object"}}},"defense":{"type":"object","description":"{ \"library\": \"<slug>\" } or { \"defenders\": [...] } (man coverage by position letter).","properties":{"library":{"type":"string"},"defenders":{"type":"array","items":{"type":"object"}}}},"side":{"type":"string","enum":["offense","defense"]},"ruleset":{"type":"string","enum":["ifaf-2023","league-6v6","nfl-flag","league"],"description":"Default: ifaf-2023 for 5v5 and 7v7, nfl-flag for nfl5, league-6v6 for 6v6, league for 4v4, 8v8 and 9v9."}}},"minItems":1,"maxItems":8,"description":"1 to 8 plays (a scenario: the same offense against two defenses is two plays)."},"name":{"type":"string","maxLength":40,"description":"A name for the set of plays (defaults to the first play's name)."},"allowAdjustments":{"type":"boolean","description":"Accept changes needed to fit the field (then tell the coach). Default false: they are errors."},"parent":{"type":"string","description":"The id of a draft this one revises (from an earlier link)."}},"required":["plays"]}}}},"responses":{"200":{"description":"Checked (and, for draft, stored)","content":{"application/json":{"schema":{"type":"object","description":"ok, plays (exactly as stored), contentHash, changes, issues, rules, analysis, analysisPartial, caveat, assistantNotes; create also has draft { id, url, previewUrl, expiresAt, reused }."}}}},"422":{"description":"The plays have errors; nothing stored. Fix them and send again.","content":{"application/json":{"schema":{"type":"object","description":"ok, plays (exactly as stored), contentHash, changes, issues, rules, analysis, analysisPartial, caveat, assistantNotes; create also has draft { id, url, previewUrl, expiresAt, reused }."}}}},"429":{"description":"A limit was reached; try later."},"503":{"description":"Temporarily unavailable."}}}}}}