{"openapi": "3.1.0", "info": {"title": "TopSpin Club API", "version": "1.0.0", "description": "Club-scoped API. Money uses decimal strings. Timestamps use ISO 8601. Collection reads use stable ID cursors. Request examples are available in the club integration guide."}, "paths": {"/api/v1/clubs/{slug}/data/members/": {"get": {"summary": "List members", "description": "Required scope: members:read", "operationId": "list_members", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/courts/": {"get": {"summary": "List courts", "description": "Required scope: schedule:read", "operationId": "list_courts", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/reservation-types/": {"get": {"summary": "List reservation-types", "description": "Required scope: schedule:read", "operationId": "list_reservation_types", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/reservations/": {"get": {"summary": "List reservations", "description": "Required scope: schedule:read", "operationId": "list_reservations", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/court-holds/": {"get": {"summary": "List court-holds", "description": "Required scope: schedule:read", "operationId": "list_court_holds", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/programs/": {"get": {"summary": "List programs", "description": "Required scope: schedule:read", "operationId": "list_programs", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/plans/": {"get": {"summary": "List plans", "description": "Required scope: members:read", "operationId": "list_plans", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/memberships/": {"get": {"summary": "List memberships", "description": "Required scope: members:read", "operationId": "list_memberships", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/invoices/": {"get": {"summary": "List invoices", "description": "Required scope: finance:read", "operationId": "list_invoices", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/payments/": {"get": {"summary": "List payments", "description": "Required scope: finance:read", "operationId": "list_payments", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/ledger/": {"get": {"summary": "List ledger", "description": "Required scope: finance:read", "operationId": "list_ledger", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/registrations/": {"get": {"summary": "List registrations", "description": "Required scope: desk:read", "operationId": "list_registrations", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/data/work/": {"get": {"summary": "List work", "description": "Required scope: operations:read", "operationId": "list_work", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Paginated collection. next_after is null at the end."}}, "security": [{"bearerAuth": []}]}}, "/api/v1/clubs/{slug}/goals/": {"get": {"summary": "Goals", "description": "Uses the same business rules as the club application. Required scope: operations:read Paginated goal records with latest 20 updates each. Numeric progress is the latest recorded observation, not an automatic calculation. No communication is sent.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "id", "in": "query", "schema": {"type": "integer", "minimum": 1}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100}}, {"name": "after", "in": "query", "schema": {"type": "integer", "minimum": 0}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "goals_get"}}, "/api/v1/clubs/{slug}/goals/history/": {"get": {"summary": "Goal History", "description": "Uses the same business rules as the club application. Required scope: operations:read Newest-first relationship/goal history. Supply goal_id or player_id; both intersect. Follow next_before until null for full history. Actor and evidence remain attached to each update. A communication plan is not delivery.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "goal_id", "in": "query", "schema": {"type": "integer", "minimum": 1}}, {"name": "player_id", "in": "query", "schema": {"type": "integer", "minimum": 1}}, {"name": "before", "in": "query", "schema": {"type": "integer", "minimum": 1}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 20}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "goal_history_get"}}, "/api/v1/clubs/{slug}/goals/create/": {"post": {"summary": "Create Goal Record", "description": "Uses the same business rules as the club application. Required scope: operations:write Articulate a club outcome. Optional numeric targets require a named measure. A stable request_key prevents duplicate creation.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "create_goal_record_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"title": {"type": "string", "minLength": 1, "maxLength": 160}, "outcome": {"type": "string", "minLength": 1, "maxLength": 10000}, "responsible_role": {"type": "string", "maxLength": 100}, "due": {"type": "string", "format": "date"}, "metric": {"type": "string", "maxLength": 100}, "baseline": {"type": "string"}, "target": {"type": "string"}, "request_key": {"type": "string", "minLength": 1, "maxLength": 64, "description": "Stable client request key. Reuse the same value when retrying the same booking."}}, "required": ["title", "outcome", "request_key"]}}}}}}, "/api/v1/clubs/{slug}/goals/{pk}/updates/": {"post": {"summary": "Add Goal Update", "description": "Uses the same business rules as the club application. Required scope: operations:write Append evidence, a decision or a communication plan. Optional player_id links relationship context. This records a plan, never sends a message. Status is explicitly set by the actor; numeric observations do not auto-complete goals.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "pk", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "add_goal_update_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"kind": {"type": "string", "enum": ["observation", "decision", "communication_plan"]}, "note": {"type": "string", "minLength": 1, "maxLength": 10000}, "evidence": {"type": "string", "maxLength": 500}, "value": {"type": "string"}, "next_action": {"type": "string", "maxLength": 500}, "next_due": {"type": "string", "format": "date"}, "status": {"type": "string", "enum": ["active", "at_risk", "achieved", "paused"]}, "player_id": {"type": "integer", "minimum": 1}, "request_key": {"type": "string", "minLength": 1, "maxLength": 64, "description": "Stable client request key. Reuse the same value when retrying the same booking."}}, "required": ["kind", "note", "request_key"]}}}}}}, "/api/v1/clubs/{slug}/intelligence/playbooks/": {"get": {"summary": "Intelligence Playbooks", "description": "Uses the same business rules as the club application. Required scope: operations:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "intelligence_playbooks_get"}}, "/api/v1/clubs/{slug}/members/{player_id}/profile/": {"get": {"summary": "Member Profile", "description": "Uses the same business rules as the club application. Required scope: members:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "player_id", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "member_profile_get"}}, "/api/v1/clubs/{slug}/attendance/": {"get": {"summary": "Attendance", "description": "Uses the same business rules as the club application. Required scope: desk:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "date", "in": "query", "schema": {"type": "string", "format": "date"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "attendance_get"}}, "/api/v1/clubs/{slug}/programs/{pk}/dates/": {"get": {"summary": "Program Dates", "description": "Uses the same business rules as the club application. Required scope: schedule:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "pk", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "program_dates_get"}}, "/api/v1/clubs/{slug}/quote/": {"post": {"summary": "Booking Quote", "description": "Uses the same business rules as the club application. Required scope: schedule:read Read-only estimate; does not reserve inventory or guarantee eligibility. Availability and booking policy are checked again on creation.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "booking_quote_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"court_id": {"type": "integer", "minimum": 1}, "type_id": {"type": "integer", "minimum": 1}, "start": {"type": "string", "format": "date-time"}, "end": {"type": "string", "format": "date-time"}}, "required": ["court_id", "type_id", "start", "end"]}}}}}}, "/api/v1/clubs/{slug}/arrivals/{player_id}/": {"get": {"summary": "Arrivals", "description": "Uses the same business rules as the club application. Required scope: desk:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "player_id", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "arrivals_get"}}, "/api/v1/clubs/{slug}/calendar/": {"get": {"summary": "Calendar", "description": "Uses the same business rules as the club application. Required scope: schedule:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "date", "in": "query", "schema": {"type": "string", "format": "date"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "calendar_get"}}, "/api/v1/clubs/{slug}/search/": {"get": {"summary": "Search", "description": "Uses the same business rules as the club application. Required scope: members:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "q", "in": "query", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "search_get"}}, "/api/v1/clubs/{slug}/reservations/": {"post": {"summary": "Reservations", "description": "Uses the same business rules as the club application. Required scope: schedule:write ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "reservations_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"court_id": {"type": "integer", "minimum": 1}, "type_id": {"type": "integer", "minimum": 1}, "owner_id": {"type": "integer", "minimum": 1}, "start": {"type": "string", "format": "date-time"}, "end": {"type": "string", "format": "date-time"}, "request_key": {"type": "string", "minLength": 1, "maxLength": 64, "description": "Stable client request key. Reuse the same value when retrying the same booking."}}, "required": ["court_id", "type_id", "owner_id", "start", "end"]}}}}}}, "/api/v1/clubs/{slug}/reservations/{pk}/cancel/": {"post": {"summary": "Cancel", "description": "Uses the same business rules as the club application. Required scope: schedule:write ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "pk", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "cancel_post", "requestBody": {"required": false, "content": {"application/json": {"schema": {"type": "object", "properties": {}, "required": []}}}}}}, "/api/v1/clubs/{slug}/blocks/": {"post": {"summary": "Blocks", "description": "Uses the same business rules as the club application. Required scope: schedule:write ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "blocks_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"court_id": {"type": "integer", "minimum": 1}, "start": {"type": "string", "format": "date-time"}, "end": {"type": "string", "format": "date-time"}, "reason": {"type": "string", "minLength": 1}}, "required": ["court_id", "start", "end", "reason"]}}}}}}, "/api/v1/clubs/{slug}/series/": {"post": {"summary": "Series", "description": "Uses the same business rules as the club application. Required scope: schedule:write Preview first with commit omitted. To commit, include commit=true, type_id, owner_id, a stable request_key and the digest returned by the preview. Conflicts or changed inventory reject the whole series.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "series_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"court_ids": {"type": "array", "items": {"type": "integer", "minimum": 1}, "minItems": 1}, "type_id": {"type": "integer", "minimum": 1}, "owner_id": {"type": "integer", "minimum": 1}, "rule": {"type": "string", "example": "FREQ=WEEKLY;BYDAY=MO"}, "start_date": {"type": "string", "format": "date"}, "end_date": {"type": "string", "format": "date"}, "start_time": {"type": "string", "example": "09:00"}, "duration_minutes": {"type": "integer", "minimum": 1, "maximum": 1440}, "commit": {"type": "boolean"}, "digest": {"type": "string"}, "request_key": {"type": "string", "minLength": 1, "maxLength": 64, "description": "Stable client request key. Reuse the same value when retrying the same booking."}}, "required": ["court_ids", "rule", "start_date", "end_date", "start_time", "duration_minutes"]}}}}}}, "/api/v1/clubs/{slug}/work/{pk}/": {"post": {"summary": "Finish", "description": "Uses the same business rules as the club application. Required scope: operations:write Dismissal requires a reason. Snoozing requires a future until timestamp.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "pk", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "finish_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string", "enum": ["done", "snoozed", "dismissed"]}, "reason": {"type": "string"}, "until": {"type": "string", "format": "date-time"}}, "required": ["status"]}}}}}}, "/api/v1/clubs/{slug}/waivers/{player_id}/": {"get": {"summary": "Waivers", "description": "Uses the same business rules as the club application. Required scope: desk:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "player_id", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "waivers_get"}}, "/api/v1/clubs/{slug}/sign/": {"post": {"summary": "Sign", "description": "Uses the same business rules as the club application. Required scope: desk:write The credential actor must be the signer or explicitly authorized guardian. Staff integration access does not itself authorize signing for another person.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "sign_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"player_id": {"type": "integer", "minimum": 1}, "waiver_id": {"type": "integer", "minimum": 1}, "signature": {"type": "string", "description": "PNG data URL of the signature captured from the signer."}}, "required": ["player_id", "waiver_id", "signature"]}}}}}}, "/api/v1/clubs/{slug}/check-in/": {"post": {"summary": "Check In", "description": "Uses the same business rules as the club application. Required scope: desk:write Send exactly one reservation_id or registration_id. For a session enrollment, include the dated event_id. The player must have a place and current waivers. Check-in is only available on the club-local date.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "check_in_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"player_id": {"type": "integer", "minimum": 1}, "reservation_id": {"type": "integer", "minimum": 1}, "registration_id": {"type": "integer", "minimum": 1}, "event_id": {"type": "integer", "minimum": 1}}, "required": ["player_id"]}}}}}}, "/api/v1/clubs/{slug}/registrations/": {"post": {"summary": "Registration", "description": "Uses the same business rules as the club application. Required scope: desk:write Drop-ins require event_id. Whole-session enrollments omit event_id. The response status is registered or waitlisted.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "registration_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"program_id": {"type": "integer", "minimum": 1}, "player_id": {"type": "integer", "minimum": 1}, "event_id": {"type": "integer", "minimum": 1}}, "required": ["program_id", "player_id"]}}}}}}, "/api/v1/clubs/{slug}/ledger.csv": {"get": {"summary": "Ledger Export", "description": "Uses the same business rules as the club application. Required scope: finance:read ", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "ledger_export_get"}}, "/api/v1/clubs/{slug}/campaigns/{pk}/": {"post": {"summary": "Campaign", "description": "Uses the same business rules as the club application. Required scope: communications:write POST {} previews eligible recipients. Approval requires approve=true and the preview digest. This endpoint does not send a campaign.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "pk", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "campaign_post", "requestBody": {"required": false, "content": {"application/json": {"schema": {"type": "object", "properties": {"approve": {"type": "boolean"}, "digest": {"type": "string"}}, "required": []}}}}}}, "/api/v1/clubs/{slug}/consent/": {"get": {"summary": "Consent", "description": "Uses the same business rules as the club application. Scope depends on method. Applies to the authenticated credential actor. GET returns the exact current disclosures; POST must include one unchanged disclosure and explicit agreement. Does not grant consent for arbitrary members.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "consent_get"}, "post": {"summary": "Consent", "description": "Uses the same business rules as the club application. Scope depends on method. Applies to the authenticated credential actor. GET returns the exact current disclosures; POST must include one unchanged disclosure and explicit agreement. Does not grant consent for arbitrary members.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "consent_post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"channel": {"type": "string", "enum": ["sms", "email"]}, "purpose": {"type": "string", "enum": ["transactional", "marketing"]}, "address": {"type": "string"}, "agreed": {"type": "boolean"}, "disclosure": {"type": "string"}}, "required": ["channel", "purpose", "address", "agreed", "disclosure"]}}}}}}, "/api/v1/clubs/{slug}/invoices/{pk}/checkout/": {"post": {"summary": "Checkout", "description": "Uses the same business rules as the club application. Required scope: finance:write Creates a checkout session in the club merchant account. Returns url. Payment is recorded only after a verified provider webhook.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "pk", "in": "path", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "Success"}, "201": {"description": "Created"}, "400": {"description": "Invalid request"}, "401": {"description": "Authentication required"}, "403": {"description": "Insufficient access"}}, "security": [{"bearerAuth": []}], "operationId": "checkout_post", "requestBody": {"required": false, "content": {"application/json": {"schema": {"type": "object", "properties": {}, "required": []}}}}}}}, "components": {"securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer"}}}}