Product Requirements Document

PRD: OpenRally Protocol

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.

Shippedv1.0Updated 2026-03-06

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.

Problem Statement

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.

Distribution Chain

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.

Protocol Decisions

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.

Canonical Sports (v1.0)

Padel

openrally:sport:padel

Tennis

openrally:sport:tennis

Pickleball

openrally:sport:pickleball

Squash

openrally:sport:squash

Badminton

openrally:sport:badminton

Table Tennis

openrally:sport:table-tennis

Padbol

openrally:sport:padbol

Beach Tennis

openrally:sport:beach-tennis

Extension mechanism: x-acme:sport:jai-alai — implementers can define custom sports using their namespace.

Booking Lifecycle (State Machine)

StateDescriptionTransitions
availableSlot is open for booking→ held (hold) or → confirmed (direct book)
heldTemporarily reserved, TTL enforced (5-10 min)→ confirmed (confirm) or → available (expire/release)
confirmedBooking is active→ completed (past end_time) or → cancelled (cancel)
completedBooking occurred (past tense)Terminal state
cancelledBooking was cancelledTerminal state
blockedAdministratively blocked (maintenance, private event)→ available (admin action)

API Endpoints (21 total)

MethodPathDescriptionSpec
GET/openrally/v1/Protocol metadata + capabilitiesCore
GET/openrally/v1/facilitiesList facilities (paginated, filterable)Core
GET/openrally/v1/facilities/{id}Get facility detailsCore
GET/openrally/v1/facilities/{id}/resourcesList resources (courts/fields) at facilityCore
GET/openrally/v1/facilities/{id}/resources/{id}Get resource detailsCore
GET/openrally/v1/facilities/{id}/availabilityQuery available slots by sport, date, time rangeCore
GET/openrally/v1/facilities/{id}/pricingGet pricing for a specific slot using calculate_member_priceCore
GET/openrally/v1/sportsList supported sportsCore
POST/openrally/v1/holdsCreate a time-limited hold (lease) on a slotCore
GET/openrally/v1/holds/{id}Get hold statusCore
DELETE/openrally/v1/holds/{id}Release a holdCore
POST/openrally/v1/bookingsCreate a booking (from hold or direct)Core
GET/openrally/v1/bookingsList bookings (paginated, filterable)Core
GET/openrally/v1/bookings/{id}Get booking detailsCore
PATCH/openrally/v1/bookings/{id}Modify a booking (reschedule, change court)Core
DELETE/openrally/v1/bookings/{id}Cancel a bookingCore
GET/openrally/v1/facilities/{id}/add-onsList add-ons a facility offers, with the resources each can be delivered on (0.5.0)Core
GET/openrally/v1/bookings/{id}/add-onsList add-ons added on a booking (0.5.0)Core
POST/openrally/v1/bookings/{id}/add-onsAdd 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/streamSSE real-time event streamPush

Push Spec — SSE Events

EventDescriptionDurable
availability_changedSlot became available or unavailableVOLATILE
booking_createdNew booking confirmed on any channelDURABLE
booking_modifiedExisting booking changedDURABLE
booking_cancelledBooking cancelled on any channelDURABLE
hold_createdSlot held (lease created)VOLATILE
hold_releasedHold expired or manually releasedVOLATILE
facility_updatedOperating hours, court status changedDURABLE

Durable events must never be dropped. Volatile events (availability) may be dropped under backpressure. Clients reconnect with Last-Event-ID for replay.

Performance Requirements

Operationp50p99Max
Availability query< 200ms< 500ms3,000ms
Hold creation< 150ms< 400ms2,000ms
Booking confirmation< 300ms< 800ms5,000ms
Booking retrieval< 100ms< 300ms1,000ms
Booking modification< 300ms< 800ms5,000ms
Booking cancellation< 200ms< 500ms3,000ms
SSE event delivery< 500ms< 2,000ms5,000ms

Compliance & Certification

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.

OpenRally vs. Existing Standards

DimensionOTA (Travel)OpenActiveOpenRally
DomainHotels, flights, carsUK physical activitySports facility booking
FormatXML (legacy) + JSON (2.0)JSON-LDJSON
TransportSOAP + RESTRESTREST + SSE
Real-timePush notifications (NotifRQ)RPDE feeds (polling)SSE (true push)
Booking flowAvail → Book → Modify → CancelC1 → C2 → B (checkpoints)Avail → Hold → Book → Modify → Cancel
IdentityHotel codes (per-GDS)URLs (per-seller)Protocol URIs (or://)
SportsNoneGeneric activity typesFirst-class sport enum
Channel mgmtYes (core use case)NoYes (core design goal)
GovernanceConsortium (paid)ODI + Sport EnglandOpen (Apache 2.0, GitHub)
CertificationNoneSelf-certificationAutomated test suite

Risks & Mitigations

No adoption — platforms ignore the standard

HighCritical

Ship Setpoint as reference implementation first. Prove the value. Build SDK/tools to lower adoption cost.

OpenActive conflict — perceived as competing standard

MediumHigh

Position as compatible superset. Engage OpenActive community. Propose alignment.

Over-engineering v1 — too complex, nobody implements

MediumHigh

Strict scope: core booking only. No pricing, no memberships in v1.

Fragmented implementations — like OTA's drift

MediumHigh

Automated test suite. Strict schema validation. Certification badges.

Platform resistance — incumbents refuse to adopt

HighMedium

Don't need incumbents first. Enable new entrants and aggregators. Network effects pull incumbents in.

Implementation Roadmap

1

Reference Implementation (v0.1) ✅

Shipped 6 Mar 2026
  • ✅ Rust/Axum server on Fly.io Tokyo (openrally-server.fly.dev)
  • ✅ 16 REST endpoints: discovery, availability, holds, bookings (CRUD), SSE stream
  • ✅ Adapter over existing Setpoint Supabase DB (no data duplication)
  • ✅ SHA-256 API key auth, rate limiting (300 req/min), moka L1 cache
  • ✅ Background services: slot materializer (60s), hold expiry (30s), event fan-out (PgListener)
  • ✅ 90 integration tests (v0.16 alignment verified), Dockerfile + .dockerignore, fly.toml
2

v1.0 Endpoint Gaps ✅

Shipped 9 Mar 2026
  • ✅ GET /bookings — list bookings (paginated, filterable by status/resource/sport/date)
  • ✅ PATCH /bookings/{id} — modify booking (slot swap: reschedule, change court)
  • ✅ DELETE /bookings/{id} — cancel booking (confirmed only, releases slot, preserves record)
3

Specification & Publication ✅

Shipped 10 Mar 2026
  • ✅ Publish OpenAPI 3.1 definition (machine-readable spec) — protocol/spec/openapi.yaml
  • ✅ Publish JSON Schema definitions for all request/response types — protocol/spec/schemas/ (19 files)
  • ✅ Stripe-inspired API docs site — apps/openrally-docs/ (Next.js, build-time YAML parsing, 20+ pages)
  • Consider openrally/ GitHub org for spec artifacts only — reference implementation stays in Setpoint monorepo
4

Test Suite & SDK

Month 4-5
  • Build open-source compliance test suite
  • Build TypeScript SDK (@openrally/sdk)
  • Build Python SDK (openrally-python)
  • Self-certify Setpoint at OpenRally Full level
5

Community & Adoption

Month 5-8
  • Engage OpenActive community — propose compatibility bridge
  • Reach out to 3-5 sports booking platforms
  • Build OpenRally → OpenActive bridge adapter
  • Present at sports tech / padel industry events
6

Extensions

Month 8-12
  • Draft openrally:ext:pricing extension spec
  • Draft openrally:ext:identity extension spec (universal player ID)
  • Draft openrally:ext:members extension spec
  • Setpoint implements extensions as finalized

Next Steps

  • ✅ OpenAPI 3.1 specification file — protocol/spec/openapi.yaml (validated with @redocly/cli)
  • ✅ JSON Schema definitions — protocol/spec/schemas/ (19 standalone files)
  • ✅ Stripe-inspired API docs site — apps/openrally-docs/ (openrally.vercel.app)
  • TypeScript SDK (@openrally/sdk) — client library for consumers
  • Compliance test suite design — what the automated tester validates

Out of Scope (v1.0)

  • Pricing / rate management — payment-agnostic; pricing is implementation-specific
  • Memberships & plans — extension module for v2.0
  • Programs & classes — extension module for v2.0
  • Customer/player identity — extension module for v2.0 (universal player ID)
  • Payment processing — deliberately excluded
  • Loyalty & credits — extension module for v2.0
  • Reviews & ratings — extension module for v2.0
  • Access control (door locks) — implementation-specific integration