Product Requirements Document
The first open protocol for sports facility booking. A vendor-neutral standard that enables facility management systems, channel managers, aggregators, and booking apps to exchange availability and reservation data — the way OpenTravel (OTA) standardized hotels and flights.
The first open protocol for sports facility booking. A vendor-neutral standard that enables facility management systems, channel managers, aggregators, and booking apps to exchange availability and reservation data — the way OpenTravel (OTA) standardized hotels and flights.
For Facilities
Locked into one booking platform with zero distribution options. Cannot list courts on multiple channels simultaneously. Switching platforms means losing all booking history and customer relationships.
For Players
Must check 3-5 separate apps (Playtomic, CourtReserve, MATCHi) to find available courts. Different accounts, different payment methods per platform. No unified booking history across facilities.
For Developers
Every integration is custom, expensive, and fragile. Aggregators resort to scraping proprietary APIs that break regularly. No standard language means every connection is a one-off engineering project.
Facility
Padel Club, Tennis Center
PMS
Setpoint, CourtReserve, custom
Channel Manager
Syncs inventory across channels
Consumer
Playtomic, Google, own app
Every arrow speaks OpenRally. Same protocol at every connection point.
Governance
Neutral open standard
Vendor-neutral like OTA. Maximum adoption potential. Apache 2.0 license. GitHub-based RFC process.
Scope (v1)
Core booking only
Availability, hold, book, modify, cancel. Ship fast, prove value. Extensions (pricing, memberships, identity) come in v2.
OpenActive
Compatible superset
Respect existing work and enable interop, but go far beyond. FacilityUse/Slot maps to Resource/Slot. C1/C2/B maps to Hold/Book.
Distribution
Full distribution chain
Facility → PMS → Channel Manager → Aggregator/Marketplace. Same protocol at every connection point. Enables channel managers to exist for sports.
Specs
Core + Push (2 specs)
Core = REST/JSON request-response for CRUD. Push = SSE for real-time notifications. Pattern-based, not role-based — simpler than OTA's fragmented approach.
Transport
REST + JSON + SSE
REST for CRUD (universal). JSON-only (no XML). SSE for real-time push (HTTP-native, simpler than WebSocket, works through CDNs).
Payments
Payment-agnostic
Protocol handles booking lifecycle, not money. Payment is an implementation detail. Like OTA — references payment but doesn't mandate a processor.
Multi-sport
Sport as first-class concept
Canonical sport enum (padel, tennis, pickleball, squash, badminton, table-tennis, padbol, beach-tennis) with extension mechanism for custom sports.
Identifiers
Protocol-defined IDs (or://)
Globally unique URIs: or://{provider}/{type}/{local_id}. No central registry needed — provider namespace prevents collisions. Supports cross-platform aliases.
Google Maps
Reserve with Google compatible from day one
Protocol data model maps directly to Google Actions Center feeds (Merchant → Facility, Service → Sport booking, Availability → Slots, room_id → Court). Booking server endpoints align with Google's v3 API. Facilities appear on Google Maps/Search with a 'Book' button.
Padel
openrally:sport:padelTennis
openrally:sport:tennisPickleball
openrally:sport:pickleballSquash
openrally:sport:squashBadminton
openrally:sport:badmintonTable Tennis
openrally:sport:table-tennisPadbol
openrally:sport:padbolBeach Tennis
openrally:sport:beach-tennisExtension mechanism: x-acme:sport:jai-alai — implementers can define custom sports using their namespace.
| State | Description | Transitions |
|---|---|---|
available | Slot is open for booking | → held (hold) or → confirmed (direct book) |
held | Temporarily reserved, TTL enforced (5-10 min) | → confirmed (confirm) or → available (expire/release) |
confirmed | Booking is active | → completed (past end_time) or → cancelled (cancel) |
completed | Booking occurred (past tense) | Terminal state |
cancelled | Booking was cancelled | Terminal state |
blocked | Administratively blocked (maintenance, private event) | → available (admin action) |
| Method | Path | Description | Spec |
|---|---|---|---|
| GET | /openrally/v1/ | Protocol metadata + capabilities | Core |
| GET | /openrally/v1/facilities | List facilities (paginated, filterable) | Core |
| GET | /openrally/v1/facilities/{id} | Get facility details | Core |
| GET | /openrally/v1/facilities/{id}/resources | List resources (courts/fields) at facility | Core |
| GET | /openrally/v1/facilities/{id}/resources/{id} | Get resource details | Core |
| GET | /openrally/v1/facilities/{id}/availability | Query available slots by sport, date, time range | Core |
| GET | /openrally/v1/facilities/{id}/pricing | Get pricing for a specific slot using calculate_member_price | Core |
| GET | /openrally/v1/sports | List supported sports | Core |
| POST | /openrally/v1/holds | Create a time-limited hold (lease) on a slot | Core |
| GET | /openrally/v1/holds/{id} | Get hold status | Core |
| DELETE | /openrally/v1/holds/{id} | Release a hold | Core |
| POST | /openrally/v1/bookings | Create a booking (from hold or direct) | Core |
| GET | /openrally/v1/bookings | List bookings (paginated, filterable) | Core |
| GET | /openrally/v1/bookings/{id} | Get booking details | Core |
| PATCH | /openrally/v1/bookings/{id} | Modify a booking (reschedule, change court) | Core |
| DELETE | /openrally/v1/bookings/{id} | Cancel a booking | Core |
| GET | /openrally/v1/facilities/{id}/add-ons | List add-ons a facility offers, with the resources each can be delivered on (0.5.0) | Core |
| GET | /openrally/v1/bookings/{id}/add-ons | List add-ons added on a booking (0.5.0) | Core |
| POST | /openrally/v1/bookings/{id}/add-ons | Add an add-on onto a booking — idempotent, hardware booked by the PMS afterwards (0.5.0) | Core |
| DELETE | /openrally/v1/bookings/{id}/add-ons/{id} | Remove an add-on from a booking and take its price back off it (0.5.0) | Core |
| GET | /openrally/v1/stream | SSE real-time event stream | Push |
| Event | Description | Durable |
|---|---|---|
availability_changed | Slot became available or unavailable | VOLATILE |
booking_created | New booking confirmed on any channel | DURABLE |
booking_modified | Existing booking changed | DURABLE |
booking_cancelled | Booking cancelled on any channel | DURABLE |
hold_created | Slot held (lease created) | VOLATILE |
hold_released | Hold expired or manually released | VOLATILE |
facility_updated | Operating hours, court status changed | DURABLE |
Durable events must never be dropped. Volatile events (availability) may be dropped under backpressure. Clients reconnect with Last-Event-ID for replay.
| Operation | p50 | p99 | Max |
|---|---|---|---|
| Availability query | < 200ms | < 500ms | 3,000ms |
| Hold creation | < 150ms | < 400ms | 2,000ms |
| Booking confirmation | < 300ms | < 800ms | 5,000ms |
| Booking retrieval | < 100ms | < 300ms | 1,000ms |
| Booking modification | < 300ms | < 800ms | 5,000ms |
| Booking cancellation | < 200ms | < 500ms | 3,000ms |
| SSE event delivery | < 500ms | < 2,000ms | 5,000ms |
Basic
OpenRally Compatible
Discovery + Availability endpoints
Core
OpenRally Certified
Basic + Holds + Bookings + Modify + Cancel
Full
OpenRally Full
Core + Push (SSE) + all event types
Unlike OTA (no enforcement), OpenRally includes an open-source automated compliance test suite. Providers self-certify by running the test harness against their implementation.
| Dimension | OTA (Travel) | OpenActive | OpenRally |
|---|---|---|---|
| Domain | Hotels, flights, cars | UK physical activity | Sports facility booking |
| Format | XML (legacy) + JSON (2.0) | JSON-LD | JSON |
| Transport | SOAP + REST | REST | REST + SSE |
| Real-time | Push notifications (NotifRQ) | RPDE feeds (polling) | SSE (true push) |
| Booking flow | Avail → Book → Modify → Cancel | C1 → C2 → B (checkpoints) | Avail → Hold → Book → Modify → Cancel |
| Identity | Hotel codes (per-GDS) | URLs (per-seller) | Protocol URIs (or://) |
| Sports | None | Generic activity types | First-class sport enum |
| Channel mgmt | Yes (core use case) | No | Yes (core design goal) |
| Governance | Consortium (paid) | ODI + Sport England | Open (Apache 2.0, GitHub) |
| Certification | None | Self-certification | Automated test suite |
No adoption — platforms ignore the standard
HighCriticalShip Setpoint as reference implementation first. Prove the value. Build SDK/tools to lower adoption cost.
OpenActive conflict — perceived as competing standard
MediumHighPosition as compatible superset. Engage OpenActive community. Propose alignment.
Over-engineering v1 — too complex, nobody implements
MediumHighStrict scope: core booking only. No pricing, no memberships in v1.
Fragmented implementations — like OTA's drift
MediumHighAutomated test suite. Strict schema validation. Certification badges.
Platform resistance — incumbents refuse to adopt
HighMediumDon't need incumbents first. Enable new entrants and aggregators. Network effects pull incumbents in.