A comprehensive booking system plugin for MedusaJS that enables you to define resources, configure availability rules, set up pricing, and manage bookings through both admin and storefront interfaces.
The Medusa Booking System Plugin extends your Medusa e-commerce platform with powerful booking capabilities. Whether you're managing hotel rooms, equipment rentals, appointment scheduling, or any time-based resource, this plugin provides the tools you need to:
- Define Resources: Create bookable resources with custom types and configurations
- Configure Availability: Set up flexible availability rules with priority-based scheduling
- Booking Rules: Define policy rules (payment, confirmation, reservation TTL) with global or per-resource scope
- Manage Pricing: Configure dynamic pricing based on dates, quantities, and custom rules
- Handle Bookings: Process bookings through carts, orders, and allocations
- Admin Dashboard: Manage all aspects of your booking system through an intuitive admin interface
- Resource Management: Create and manage bookable resources with product integration
- Availability Rules: Define complex availability patterns with priority-based rule system
- Booking Rules: Policy rules for payment requirements, confirmation flow, reservation TTL, and custom config; scope can be global or per-resource with priority and validity windows
- Pricing Configuration: Set up flexible pricing models with multiple price points;
- Booking Workflows: Complete booking flow from cart to order creation
- Resource Allocations: Track and manage time-based resource allocations
- Status Management: Control resource visibility with draft/published status
- Admin Interface: Full-featured admin dashboard for managing bookings, resources, and booking rules
Resources can be configured with different types (e.g., "room", "equipment", "appointment") and support:
- Custom pricing units (hourly, daily, weekly, etc.)
- Bookable/non-bookable status
- Product integration for seamless e-commerce experience
The availability system supports:
- Multiple availability rules per resource
- Priority-based rule evaluation
- Available/unavailable effects
- Date range validity
- Custom rule configurations
- Active/inactive rule states
Booking rules define policy behavior applied at evaluation time:
- Scope:
global(all resources) orresource(specific resource IDs) - Policy fields:
require_payment,require_confirmation,reservation_ttl_seconds - Optional:
configuration(custom JSON),priority,valid_from/valid_until,is_active - Resolution: Rules are merged by priority; store and admin can resolve effective rules for a given time (and optionally resource) via the rules endpoints.
Flexible pricing configuration:
- Multiple pricing configurations per resource
- Currency-based pricing
- Product variant integration
- Node.js >= 20
- MedusaJS v2.7.0 or higher
- PostgreSQL database
Add the booking system plugin to your Medusa application:
npm install @rsc-labs/medusa-booking-systemOr if using yarn:
yarn add @rsc-labs/medusa-booking-systemAdd the plugin to your Medusa configuration. In your medusa-config.ts or medusa-config.js:
import { defineConfig } from "@medusajs/framework";
export default defineConfig({
// ... your existing config
plugins: [
// ... your existing modules
{
resolve: "@rsc-labs/medusa-booking-system",
options: {},
},
],
});Generate the database migrations for the booking module:
npx medusa db:generate bookingModuleApply the migrations to your database:
npx medusa db:migrateThe plugin provides two sets of API endpoints:
Public-facing endpoints for customers to browse and book resources.
GET /store/booking-resources- List all available booking resourcesGET /store/booking-resources/[id]- Get a specific booking resource (optional query:region_idfor region-based calculated pricing)GET /store/booking-resources/[id]/availability- Get availability informationGET /store/booking-resources/[id]/rules- Get resolved booking rules for the resource (optional query:evaluation_timeas ISO date string)POST /store/booking-resources/[id]/hold- Hold a resource for a time period
POST /store/booking-carts- Create a new booking cartGET /store/booking-carts/[id]- Get cart with booking line itemsPOST /store/booking-carts/[id]- Update cart customer informationPOST /store/booking-carts/[id]/items- Add booking item to cartDELETE /store/booking-carts/[id]/items/[itemId]- Remove item from cartPOST /store/booking-carts/[id]/complete- Complete booking cart (creates order)
Administrative endpoints for managing the booking system.
GET /admin/booking-resources- List all booking resourcesPOST /admin/booking-resources- Create a new booking resourceGET /admin/booking-resources/[id]- Get booking resource detailsPOST /admin/booking-resources/[id]- Update booking resourceDELETE /admin/booking-resources/[id]- Delete booking resourceGET /admin/booking-resources/[id]/availability- Get availability for date rangePOST /admin/booking-resources/[id]/status- Update resource status (published/draft)
GET /admin/booking-rules- List all booking rules (with booking resources count)POST /admin/booking-rules- Create a booking ruleGET /admin/booking-rules/[id]- Get a booking rule (with booking resources count)POST /admin/booking-rules/[id]- Update a booking ruleDELETE /admin/booking-rules/[id]- Delete a booking ruleGET /admin/booking-rules/evaluate- Evaluate resolved rules (query:evaluation_timerequired, optionalbooking_resource_id)
GET /admin/booking-resources/[id]/availability-rules- List availability rulesPOST /admin/booking-resources/[id]/availability-rules- Create availability ruleGET /admin/booking-resources/[id]/availability-rules/[ruleId]- Get specific rulePOST /admin/booking-resources/[id]/availability-rules/[ruleId]- Update ruleDELETE /admin/booking-resources/[id]/availability-rules/[ruleId]- Delete rule
POST /admin/booking-resources/[id]/pricing- Create pricing configurationPOST /admin/booking-resources/[id]/pricing/[priceConfigId]- Update pricingDELETE /admin/booking-resources/[id]/pricing/[priceConfigId]- Delete pricing
GET /admin/bookings- List all bookingsPOST /admin/bookings- Create a bookingGET /admin/bookings/[id]- Get booking detailsPOST /admin/bookings/[id]/cancel- Cancel a bookingGET /admin/bookings/stats- Get booking statistics
For detailed API documentation including request/response schemas, see the Swagger/OpenAPI specification.
The admin dashboard under Booking includes:
- Overview – Booking stats and recent activity
- Resources – List and manage booking resources; create, edit, view availability, pricing, and status
- Rules – List, create, edit, and delete booking rules; test rule evaluation for a given time and optional resource
- Bookings – List and manage bookings; create and cancel
This example demonstrates the complete flow from creating a resource to booking it on the storefront.
Create a new bookable resource (e.g., a conference room):
curl -X POST http://localhost:9000/admin/booking-resources \
-H "Content-Type: application/json" \
-d '{
"booking_resource": {
"resource_type": "conference_room",
"title": "Executive Conference Room",
"subtitle": "Capacity: 20 people",
"description": "A spacious conference room with AV equipment",
"is_bookable": true,
"pricing_unit": "hour",
"pricing_unit_value": 1
}
}'Response includes the created resource with an ID (e.g., br_01HXXX...).
Set up when the resource is available:
curl -X POST http://localhost:9000/admin/booking-resources/br_01HXXX.../availability-rules \
-H "Content-Type: application/json" \
-d '{
"rule_type": "weekly",
"name": "Business Hours",
"effect": "available",
"priority": 1,
"configuration": {
"days": [1, 2, 3, 4, 5], // Monday to Friday
"start_time": "09:00",
"end_time": "17:00"
},
"is_active": true
}'Set up pricing for the resource:
curl -X POST http://localhost:9000/admin/booking-resources/br_01HXXX.../pricing \
-H "Content-Type: application/json" \
-d '{
"booking_resource_pricing_config": {
"name": "Standard Hourly Rate"
},
"booking_resource_pricing": [
{
"currency_code": "usd",
"amount": 5000, // $50.00 per hour
"min_quantity": 1,
"max_quantity": 1
}
]
}'Make the resource available on the storefront:
curl -X POST http://localhost:9000/admin/booking-resources/br_01HXXX.../status \
-H "Content-Type: application/json" \
-d '{
"status": "published"
}'Customers can fetch a resource with region-based pricing and check availability:
# Get resource with region-based calculated price
curl "http://localhost:9000/store/booking-resources/br_01HXXX...?region_id=reg_xxx"
# Check availability
curl "http://localhost:9000/store/booking-resources/br_01HXXX.../availability?startDate=2026-02-15&endDate=2026-02-20"
# Optional: get resolved booking rules for the resource
curl "http://localhost:9000/store/booking-resources/br_01HXXX.../rules?evaluation_time=2026-02-15T10:00:00Z"Customer creates a booking cart:
curl -X POST http://localhost:9000/store/booking-carts \
-H "Content-Type: application/json" \
-d '{
"region_id": "reg_xxx"
}'Customer adds the booking to their cart:
curl -X POST http://localhost:9000/store/booking-carts/[cartId]/items \
-H "Content-Type: application/json" \
-d '{
"booking_resource_id": "br_01HXXX...",
"start_date": "2026-02-15T10:00:00Z",
"end_date": "2026-02-15T14:00:00Z"
}'This creates a temporary allocation (hold) on the resource.
Customer completes the booking, which creates an order and confirms the booking:
curl -X POST http://localhost:9000/store/booking-carts/[cartId]/completeThe booking is now confirmed, and the resource allocation is finalized.
Apache 2.0
RSC Labs (https://rsoftcon.com)