{"openapi":"3.1.0","info":{"title":"Sports Rules","version":"1.0.0","summary":"Was that offside? The decision procedure, for soccer and hockey.","description":"Work an offside call through the actual decision procedure, for association football under IFAB Law 11 and ice hockey under NHL Rule 83. Applies the parts that get missed — the arm exclusion and the involvement test in soccer, the blue-line plane and the tag-up exception in hockey — and shows every step it took, so the answer can be argued with rather than just accepted.\n\n**Not for:** Not an official ruling and not a substitute for a match official. This works through published decision procedures from the inputs you supply; it cannot see the play, and the hard part of a real offside call is almost always judging the inputs rather than applying the rule. Refereeing judgement, video review protocols, and competition-specific variations are outside what this models. Rule texts belong to IFAB and the NHL and are not reproduced.\n\nReturns THREE verdicts, not two: offside, onside, and no-offside-offence. The third is a real and common outcome in soccer — an offside position without involvement in active play is not an offence.\n\nFree tier: 250 calls per UTC day per caller. Past that, endpoints return 402 with x402 payment requirements. An MCP server exposing the same capabilities is available at https://sports-rules.gumballtools.com/api/mcp.","contact":{"url":"https://github.com/bwalvoord/gumball"}},"servers":[{"url":"https://sports-rules.gumballtools.com","description":"Production"}],"externalDocs":{"url":"https://sports-rules.gumballtools.com/llms-full.txt","description":"Full documentation for agents"},"paths":{"/api/v1/offside":{"get":{"operationId":"offsideCall","summary":"Work an offside call through the decision procedure.","description":"Returns a verdict plus every step taken, with the decisive one flagged, and the warnings that carry the parts most explanations miss — the arm exclusion and the involvement test in soccer, the blue-line plane and the tag-up exception in hockey.","parameters":[{"name":"sport","in":"query","required":true,"description":"soccer applies IFAB Law 11; hockey applies NHL Rule 83. The rules are structurally opposite — what is measured, when the picture freezes, and whether position alone is an offence all differ.","schema":{"type":"string","enum":["soccer","hockey"]}},{"name":"attacker","in":"query","required":false,"description":"SOCCER, required. Attacker position along the attacking axis; larger is nearer the opponents’ goal line. Any consistent scale — only order matters.","schema":{"type":"number"}},{"name":"ball","in":"query","required":false,"description":"SOCCER, required. Ball position on the same scale.","schema":{"type":"number"}},{"name":"secondLastDefender","in":"query","required":false,"description":"SOCCER, required. The SECOND-last opponent, on the same scale. Level is onside.","schema":{"type":"number"}},{"name":"foremostPart","in":"query","required":false,"description":"SOCCER. Which part the attacker position describes. An arm or hand is refused with an explanation: only parts that could legally score count, and the boundary is the bottom of the armpit.","schema":{"type":"string"}},{"name":"restart","in":"query","required":false,"description":"SOCCER. No offside offence direct from throw-in, goal-kick, or corner-kick.","schema":{"type":"string","enum":["open-play","throw-in","goal-kick","corner-kick","free-kick","kick-off","drop-ball"]}},{"name":"inOwnHalf","in":"query","required":false,"description":"SOCCER. A player in their own half cannot be in an offside position.","schema":{"type":"boolean"}},{"name":"involvement","in":"query","required":false,"description":"SOCCER. REQUIRED once the geometry puts the player in an offside position — omitting it returns 400 rather than a guess, because an offside position is not an offence and defaulting either way would settle the call on a fact nobody supplied. Pass \"none\" to say the player did nothing, which yields a verdict of no-offside-offence.","schema":{"type":"string","enum":["none","interfering-with-play","interfering-with-opponent","gaining-advantage"]}},{"name":"lastTouch","in":"query","required":false,"description":"SOCCER. opponent-deliberate-play resets offside. A deflection, a save, or a rebound off the post or crossbar does NOT.","schema":{"type":"string","enum":["team-mate","opponent-deliberate-play","opponent-deflection","opponent-save","rebound-off-post-or-crossbar"]}},{"name":"rearSkate","in":"query","required":false,"description":"HOCKEY, required. The trailing skate in centimetres relative to the LEADING EDGE of the blue line. Negative is the neutral-zone side.","schema":{"type":"number"}},{"name":"skateOnIce","in":"query","required":false,"description":"HOCKEY. Since 2021 irrelevant on a zone entry — the line is a plane. Decisive when tagging up, where the skate must contact the line.","schema":{"type":"boolean","default":true}},{"name":"situation","in":"query","required":false,"description":"HOCKEY. zone-entry (default) or tag-up. The same skate position can give opposite answers.","schema":{"type":"string","enum":["zone-entry","tag-up"]}},{"name":"stick","in":"query","required":false,"description":"HOCKEY. Ignored, and reported as ignored. Skates decide it.","schema":{"type":"number"}}],"responses":{"200":{"description":"The call, with every step.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input. The body names the field and how to fix it.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","fix_hint","docs"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string"},"fix_hint":{"type":"string","description":"What to change before retrying."},"field":{"type":"string"},"token":{"type":"string"},"examples":{"type":"array","items":{"type":"string"}},"docs":{"type":"string","format":"uri"}}}}}}}},"402":{"description":"Free quota of 250 calls per UTC day exhausted. Body is an x402 v1 payment requirement ($0.001 per call). While settlement is disabled the body carries payment_enabled: false — wait for quota.resetsAt.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/v1/contrast":{"get":{"operationId":"offsideRuleContrast","summary":"How the two sports’ offside rules differ, dimension by dimension.","description":"Takes no parameters. Useful before reasoning about one sport using an intuition from the other, which is the commonest way to get either wrong.","responses":{"200":{"description":"The comparison.","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}