leisure — REST API
model-city-leisure is the platform's largest vertical: city places (/city-places,
points of interest), city routes (/city-routes, ordered tourist routes over places),
public spaces (/public-spaces, civic facilities with reservable resources and citizen
reservations) and ticketed events (/events, paid via Stripe). The service registers
in Eureka as leisure, so the gateway routes /api/leisure/**.
Three authorization patterns coexist:
- Public catalogue reads (places, routes, public spaces, events) — open to any authenticated user.
- Management writes (create / update / delete of catalogue entities) — require platform
admin or backoffice, verified by
ModelCityAccessAspectthroughCoreClient. - Citizen-owned resources (reservations, tickets) — the use case requires the token's
sub(X-Auth-Sub) to own the resource.
Localizable fields (name, description, …) are Map<String, String> on requests
(locale → text, with a mandatory es); responses are resolved from Accept-Language,
falling back to es. Events ticketing runs on Stripe: the web flow uses a Checkout
Session and the mobile flow a Payment Intent; a public Stripe webhook confirms
payments, and deleting an event auto-refunds its outstanding tickets.
External systems: Stripe (Checkout / Payment Intent / refunds + signed webhook),
PostgreSQL (modelcity-leisure in microservices, the single modelcity in the monolith)
and Valkey (cache: cityPlace, cityPlaces, cityRoute, cityRoutes, cityRoutePlaces,
publicSpace, publicSpaces, reservableResources, event, events). It calls core only
to resolve the caller's role on management endpoints. See the
leisure data model.
The controllers are abstract extension points (CityPlaceController, CityRouteController,
PublicSpaceController, ReservableResourceController, ReservationController,
EventController, EventTicketController, CitizenTicketController, StripeWebhookController,
SystemTrailController); the platform registers the Default* subclass as the active bean. See
the Extensibility Guide.
City places (/city-places)
| Operation | Endpoint | Page |
|---|---|---|
| List city places | GET /api/leisure/city-places | get-city-places |
| City place detail | GET /api/leisure/city-places/{id} | get-city-place |
| Create city place | POST /api/leisure/city-places | create-city-place |
| Replace city place | PUT /api/leisure/city-places/{id} | update-city-place |
| Delete city place | DELETE /api/leisure/city-places/{id} | delete-city-place |
City routes (/city-routes)
| Operation | Endpoint | Page |
|---|---|---|
| List city routes | GET /api/leisure/city-routes | get-city-routes |
| City route detail | GET /api/leisure/city-routes/{id} | get-city-route |
| List route places | GET /api/leisure/city-routes/{id}/city-places | get-city-route-places |
| Route place detail | GET /api/leisure/city-routes/{id}/city-places/{placeId} | get-city-route-place |
| Create city route | POST /api/leisure/city-routes | create-city-route |
| Replace city route | PUT /api/leisure/city-routes/{id} | update-city-route |
| Delete city route | DELETE /api/leisure/city-routes/{id} | delete-city-route |
Public spaces (/public-spaces)
| Operation | Endpoint | Page |
|---|---|---|
| List public spaces | GET /api/leisure/public-spaces | get-public-spaces |
| Public space detail | GET /api/leisure/public-spaces/{id} | get-public-space |
| Create public space | POST /api/leisure/public-spaces | create-public-space |
| Update public space | PUT /api/leisure/public-spaces/{id} | update-public-space |
| Delete public space | DELETE /api/leisure/public-spaces/{id} | delete-public-space |
| List reservable resources | GET /api/leisure/public-spaces/{publicSpaceId}/resources | get-reservable-resources |
| Create reservable resource | POST /api/leisure/public-spaces/{publicSpaceId}/resources | create-reservable-resource |
| Update reservable resource | PUT /api/leisure/public-spaces/{publicSpaceId}/resources/{resourceId} | update-reservable-resource |
| Delete reservable resource | DELETE /api/leisure/public-spaces/{publicSpaceId}/resources/{resourceId} | delete-reservable-resource |
| List resource reservations | GET /api/leisure/public-spaces/{publicSpaceId}/resources/{resourceId}/reservations | get-reservations |
| Create reservation | POST /api/leisure/public-spaces/{publicSpaceId}/resources/{resourceId}/reservations | create-reservation |
| Delete reservation | DELETE /api/leisure/public-spaces/{publicSpaceId}/resources/{resourceId}/reservations/{reservationId} | delete-reservation |
Events (/events)
| Operation | Endpoint | Page |
|---|---|---|
| List events | GET /api/leisure/events | get-events |
| Event detail | GET /api/leisure/events/{id} | get-event |
| Create event | POST /api/leisure/events | create-event |
| Update event | PUT /api/leisure/events/{id} | update-event |
| Delete event | DELETE /api/leisure/events/{id} | delete-event |
| Purchase ticket (web) | POST /api/leisure/events/{eventId}/tickets | purchase-ticket |
| List event tickets | GET /api/leisure/events/{eventId}/tickets | get-event-tickets |
| Refund ticket | POST /api/leisure/events/{eventId}/tickets/{ticketId}/refunds | refund-ticket |
| Citizen ticket history | GET /api/leisure/users/{userId}/tickets | get-citizen-tickets |
| Stripe payment webhook | POST /api/leisure/stripe/webhook | stripe-webhook |
Audit (system trails)
| Operation | Endpoint | Page |
|---|---|---|
| Query the audit log | GET /api/leisure/system-trails | get-system-trails |