{"openapi":"3.1.0","info":{"title":"Yerevan Padel Demo API","version":"1.0.0","description":"Playtomic-style racket sports API. Clubs, courts, availability, players, open matches, bookings."},"servers":[{"url":"/","description":"Same-origin"}],"tags":[{"name":"About","description":"Facility information"},{"name":"Clubs","description":"Sport clubs"},{"name":"Courts","description":"Playing courts"},{"name":"Availability","description":"Time slot availability"},{"name":"Players","description":"Registered players"},{"name":"Matches","description":"Open matches anyone can join"},{"name":"Bookings","description":"Court bookings"},{"name":"Sports","description":"Supported sports"}],"paths":{"/api/about":{"get":{"tags":["About"],"summary":"Facility/platform info","operationId":"getAbout","responses":{"200":{"description":"Facility info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/About"}}}}}}},"/api/sports":{"get":{"tags":["Sports"],"summary":"List supported sports","operationId":"listSports","responses":{"200":{"description":"Sports list","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"icon":{"type":"string"}}}}}}}}}},"/api/clubs":{"get":{"tags":["Clubs"],"summary":"List clubs","operationId":"listClubs","parameters":[{"name":"sport","in":"query","schema":{"type":"string","enum":["PADEL","TENNIS","PICKLEBALL"]}},{"name":"city","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Clubs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Club"}}}}}}}},"/api/clubs/{id}":{"get":{"tags":["Clubs"],"summary":"Club detail with courts","operationId":"getClub","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Club detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClubDetail"}}}},"404":{"description":"Not found"}}}},"/api/courts":{"get":{"tags":["Courts"],"summary":"List courts","operationId":"listCourts","parameters":[{"name":"sport","in":"query","schema":{"type":"string"}},{"name":"clubId","in":"query","schema":{"type":"integer"}},{"name":"indoor","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Courts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Court"}}}}}}}},"/api/courts/{id}":{"get":{"tags":["Courts"],"summary":"Court detail","operationId":"getCourt","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Court detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Court"}}}}}}},"/api/availability":{"get":{"tags":["Availability"],"summary":"Court availability for date","operationId":"getAvailability","parameters":[{"name":"courtId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"date","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Availability with slots","content":{"application/json":{"schema":{"type":"object","properties":{"courtId":{"type":"integer"},"date":{"type":"string"},"slots":{"type":"array","items":{"type":"object","properties":{"time":{"type":"string"},"available":{"type":"boolean"}}}}}}}}}}}},"/api/players":{"get":{"tags":["Players"],"summary":"List players","operationId":"listPlayers","parameters":[{"name":"minLevel","in":"query","schema":{"type":"number"}},{"name":"maxLevel","in":"query","schema":{"type":"number"}},{"name":"gender","in":"query","schema":{"type":"string","enum":["male","female"]}},{"name":"location","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}}],"responses":{"200":{"description":"Players","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Player"}}}}}}},"post":{"tags":["Players"],"summary":"Register a new player","operationId":"createPlayer","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","location","level"],"properties":{"name":{"type":"string"},"location":{"type":"string"},"level":{"type":"number","minimum":1,"maximum":5},"gender":{"type":"string"},"avatar":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Player"}}}}}}},"/api/players/{id}":{"get":{"tags":["Players"],"summary":"Player detail with recent matches","operationId":"getPlayer","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Player detail"},"404":{"description":"Not found"}}}},"/api/open-matches":{"get":{"tags":["Matches"],"summary":"List open matches","operationId":"listOpenMatches","parameters":[{"name":"sport","in":"query","schema":{"type":"string"}},{"name":"clubId","in":"query","schema":{"type":"integer"}},{"name":"date","in":"query","schema":{"type":"string","format":"date"}},{"name":"dateFrom","in":"query","schema":{"type":"string","format":"date"}},{"name":"dateTo","in":"query","schema":{"type":"string","format":"date"}},{"name":"minLevel","in":"query","schema":{"type":"number"}},{"name":"maxLevel","in":"query","schema":{"type":"number"}},{"name":"gender","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Open matches","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OpenMatch"}}}}}}},"post":{"tags":["Matches"],"summary":"Create open match","operationId":"createOpenMatch","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["clubId","courtId","sport","date","startTime","duration","ownerId"],"properties":{"clubId":{"type":"integer"},"courtId":{"type":"integer"},"sport":{"type":"string"},"date":{"type":"string","format":"date"},"startTime":{"type":"string"},"duration":{"type":"integer"},"minLevel":{"type":"number"},"maxLevel":{"type":"number"},"gender":{"type":"string"},"maxPlayers":{"type":"integer"},"price":{"type":"number"},"ownerId":{"type":"string"}}}}}},"responses":{"201":{"description":"Created"}}}},"/api/open-matches/{id}":{"get":{"tags":["Matches"],"summary":"Match detail","operationId":"getOpenMatch","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Match detail"}}},"delete":{"tags":["Matches"],"summary":"Cancel match","operationId":"cancelOpenMatch","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Cancelled"}}}},"/api/open-matches/{id}/join":{"post":{"tags":["Matches"],"summary":"Join match","operationId":"joinOpenMatch","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["playerId"],"properties":{"playerId":{"type":"string"}}}}}},"responses":{"200":{"description":"Joined"},"409":{"description":"Conflict"}}},"delete":{"tags":["Matches"],"summary":"Leave match","operationId":"leaveOpenMatch","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"playerId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Left"}}}},"/api/bookings":{"get":{"tags":["Bookings"],"summary":"List bookings","operationId":"listBookings","parameters":[{"name":"courtId","in":"query","schema":{"type":"integer"}},{"name":"date","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Bookings list"}}},"post":{"tags":["Bookings"],"summary":"Create booking","operationId":"createBooking","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["courtId","date","startTime","duration","playerName","playerPhone"],"properties":{"courtId":{"type":"integer"},"date":{"type":"string","format":"date"},"startTime":{"type":"string"},"duration":{"type":"integer"},"playerName":{"type":"string"},"playerPhone":{"type":"string"},"playerEmail":{"type":"string"}}}}}},"responses":{"201":{"description":"Created"},"409":{"description":"Slot conflict"}}}},"/api/bookings/{id}":{"delete":{"tags":["Bookings"],"summary":"Cancel booking","operationId":"cancelBooking","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Cancelled"}}}}},"components":{"schemas":{"About":{"type":"object","properties":{"description":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"operatingHours":{"type":"object","properties":{"open":{"type":"string"},"close":{"type":"string"}}},"features":{"type":"array","items":{"type":"string"}},"sports":{"type":"array","items":{"type":"string"}}}},"Club":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"city":{"type":"string"},"address":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"sports":{"type":"array","items":{"type":"string"}},"courtCount":{"type":"integer"}}},"ClubDetail":{"allOf":[{"$ref":"#/components/schemas/Club"},{"type":"object","properties":{"courts":{"type":"array","items":{"$ref":"#/components/schemas/Court"}}}}]},"Court":{"type":"object","properties":{"id":{"type":"integer"},"clubId":{"type":"integer"},"name":{"type":"string"},"sport":{"type":"string"},"indoor":{"type":"boolean"},"surface":{"type":"string"},"description":{"type":"string"},"features":{"type":"array","items":{"type":"string"}},"image":{"type":"string"}}},"Player":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"location":{"type":"string"},"level":{"type":"number"},"gender":{"type":"string"},"avatar":{"type":"string"}}},"OpenMatch":{"type":"object","properties":{"id":{"type":"string"},"clubId":{"type":"integer"},"courtId":{"type":"integer"},"sport":{"type":"string"},"date":{"type":"string","format":"date"},"startTime":{"type":"string"},"endTime":{"type":"string"},"duration":{"type":"integer"},"minLevel":{"type":"number"},"maxLevel":{"type":"number"},"gender":{"type":"string"},"maxPlayers":{"type":"integer"},"price":{"type":"number"},"status":{"type":"string"},"spotsLeft":{"type":"integer"},"players":{"type":"array","items":{"$ref":"#/components/schemas/Player"}}}}}}}