{"openapi":"3.1.0","info":{"title":"The Shooters Hub API","version":"1.1.0","description":"Stable discovery, search, health, and governed location endpoints for Shooters Hub integrations."},"servers":[{"url":"https://shootershub.net/api"}],"paths":{"/matches":{"get":{"operationId":"listMatches","summary":"Public match discovery","description":"Search published matches by discipline, date, location, radius, limit, and stable sort.","tags":["stable"],"parameters":[{"name":"type","in":"query","description":"One or more disciplines.","required":false,"schema":{"type":"array","items":{"type":"string"}}},{"name":"from","in":"query","description":"Inclusive start date.","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"Inclusive end date.","required":false,"schema":{"type":"string"}},{"name":"lat","in":"query","description":"Search latitude.","required":false,"schema":{"type":"number"}},{"name":"lng","in":"query","description":"Search longitude.","required":false,"schema":{"type":"number"}},{"name":"radius","in":"query","description":"Search radius in miles.","required":false,"schema":{"type":"number"}},{"name":"limit","in":"query","description":"Maximum records from 1 through 1000.","required":false,"schema":{"type":"integer","example":25}},{"name":"sort","in":"query","description":"dateAsc, dateDesc, nameAsc, nameDesc, or distance.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Published matches and discovery metadata.","content":{"application/json":{"schema":{"type":"object","required":["items","nextCursor"],"properties":{"items":{"type":"array","items":{"type":"object","required":["id","name","date"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"date":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"distanceMi":{"type":"number"}},"additionalProperties":true}},"nextCursor":{"type":"string"}},"additionalProperties":false}}}},"500":{"description":"The match discovery service could not complete the request.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","const":"Failed to fetch matches"},"detail":{"type":"string"}}}}}}}}},"/search":{"get":{"operationId":"searchShootersHub","summary":"Hybrid site search","description":"Search public matches, clubs, discussions, listings, users, and pages.","tags":["stable"],"parameters":[{"name":"q","in":"query","description":"Search query containing at least two characters.","required":true,"schema":{"type":"string"}},{"name":"type","in":"query","description":"Optional result-type filter.","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum results from 1 through 100.","required":false,"schema":{"type":"integer","example":10}},{"name":"cursor","in":"query","description":"Opaque continuation cursor returned by a previous request.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Ranked public search results.","content":{"application/json":{"schema":{"type":"object","required":["query","results","meta"],"properties":{"query":{"type":"string"},"results":{"type":"array","items":{"type":"object","additionalProperties":true}},"nextCursor":{"type":["string","null"]},"meta":{"type":"object","required":["requestId","limit"],"properties":{"requestId":{"type":"string"},"limit":{"type":"integer"},"totalAvailable":{"type":"integer"}},"additionalProperties":true}},"additionalProperties":true}}}},"400":{"description":"The requested locale is invalid.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","const":"invalid_locale"},"detail":{"type":"string"}}}}}},"500":{"description":"Search could not complete the request.","content":{"application/json":{"schema":{"type":"object","required":["ok","error","code"],"properties":{"ok":{"type":"boolean","const":false},"error":{"type":"string"},"code":{"type":"string","const":"search_failed"}},"additionalProperties":true}}}},"503":{"description":"Search is temporarily unavailable during a governed generation cutover.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","const":"search_generation_cutover_blocked"},"code":{"type":"string"}}}}}}},"x-pagination":{"kind":"cursor","requestParameter":"cursor","responseField":"nextCursor"}}},"/olc/tiles":{"post":{"operationId":"hydrateOlcTiles","summary":"Hydrate OLC tiles","description":"Resolve governed Open Location Code tile identifiers through the backend proxy.","tags":["stable"],"parameters":[],"responses":{"200":{"description":"Controlled tile hydration payload.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"The tile request is malformed.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","const":"invalid_request"},"detail":{"type":"string"}}}}}},"502":{"description":"The governed tile service did not return a usable response.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","const":"upstream_error"},"detail":{"type":"string"}}}}}}},"requestBody":{"required":true,"description":"OLC tile identifiers.","content":{"application/json":{"schema":{"type":"object","required":["tiles"],"properties":{"tiles":{"type":"array","minItems":1,"items":{"type":"string"}}},"additionalProperties":false}}}}}},"/health":{"get":{"operationId":"getServiceHealth","summary":"Service health","description":"Lightweight Next-layer liveness check for integration smoke tests.","tags":["stable"],"parameters":[],"responses":{"200":{"description":"Current service liveness and timestamp.","content":{"application/json":{"schema":{"type":"object","required":["ok","timestamp"],"properties":{"ok":{"type":"boolean","const":true},"timestamp":{"type":"string","format":"date-time"}},"additionalProperties":false}}}}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}}}}