Events and Bookings Platform

icon

A flexible engine for modern bookings

Build the booking experience 
your business needs 

Medusa is the open source booking platform built to handle complex booking flows,
dynamic pricing, and deep integrations.

Whether you're managing rooms, tickets, services, or amenities, Medusa gives you full control
with a headless booking system that adapts to your stack.

Made for modern reservation flows

A customizable reservation system without limits

From hotels to event venues to wellness services, Medusa lets you build tailored booking journeys.

Connect to the systems you already use, manage availability-based pricing, and unify customer data with a platform that’s flexible, scalable, and open.

  • Open source booking engine
  • Availability-based pricing support
  • Integration-ready with PMS systems
  • Unify customer journeys
  • API-first and headless architecture
  • Customize admin and customer portals

Deep system integrations

Connect to your PMS and beyond

Medusa’s flexible framework supports deep custom integrations with tools like Opera and CloudBeds. Sync availability, manage reservations, and keep your core operations connected in real time.

index engine illustration

Smart pricing logic

Power dynamic pricing and real-time rates

Medusa enables custom pricing strategies with flexible APIs. Pull rates from external systems or use your own algorithms to calculate availability-based prices at checkout.

Unified guest experience

Bring every service into a single journey

Medusa helps you deliver seamless experiences across every touchpoint- spa, dining, rooms, events - by integrating your systems under one headless booking system. Build bundles, upsell services, and create portals that customers actually want to use.

blueprint framework

Cloud+ platform

Open source flexibility, cloud-powered scale

Medusa gives you the freedom of open source with the reliability of cloud hosting. Build your custom reservation engine without giving up uptime, performance, or support.

blueprint cloud

User stories

Booking systems for many use cases

Medusa’s flexibility has already made it a platform of choice among customers managing digital sales of rooms, tickets, courses, and other services.

Get in touch to learn more about our work in the space.

Framework for customizations

Faster time to market with our framework

Our developer-first framework makes it easy to build custom integrations and features: from data models and workflows to UI extensions and APIs.

No hacks, no workarounds - just clean, scalable customization.

A workflow step performs a query or action in a system. Steps can receive inputs from previous steps and return data to be used in subsequent steps. You can resolve services in your steps, allowing you to build business logic involving Medusa’s core commerce modules, third-party systems, or custom systems.

create-order-in-erp.ts

sync-order-to-erp.ts

src > workflows > steps > create-order-in-erp.ts

import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
export const createOrderInERP = createStep(
"create-order-in-erp"
async (order: StepInput, { container }) => {
const erpService = container.resolve("erp")
const createdOrder = await erpService.createOrder(order)
return new StepResponse(createdOrder)
}
)

To connect multiple steps together you create a Workflow. Creating a Workflow is like writing any other function. Behind the scenes Medusa generates a representation of your workflow that enables automatic retries of steps if they fail.

create-order-in-erp.ts

sync-order-to-erp.ts

src > workflows > sync-order-to-erp.ts

import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
import { createOrderInERP, transformOrder } from "./steps"
export const syncOrderToERP = createWorkflow(
"sync-order-to-erp",
(input: WorkflowInput, { container }) => {
const medusaOrder = retrieveOrder(input.order_id)
const createdOrder = when({ medusaOrder }, ({ medusaOrder }) => {
return medusaOrder.status === "completed"
}).then(() => {
const preparedOrder = transformOrder(medusaOrder)
return createOrderInERP(preparedOrder)
})
return new WorkflowResponse(createdOrder)
}
)

If step retries don't succeed, Medusa will rollback previous steps. A rollback will call a step's compensation method, ensuring your data is kept consistent across systems.

create-order-in-erp.ts

sync-order-to-erp.ts

src > workflows > accept-quote.ts

import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
export const createOrderInERP = createStep(
"create-order-in-erp"
async (order: StepInput, { container }) => {
const erpService = container.resolve("erp")
const createdOrder = await erpService.createOrder(order)
return new StepResponse(createdOrder, createdOrder)
},
// In the face of errors, we roll back and delete the order
async (createdOrder, { container }) => {
const erpService = container.resolve("erp")
await erpService.deleteOrder(createdOrder)
}
)

You can trigger your workflows anywhere in Medusa. Use your workflows in Subscribers to start them in response to an event. Start them in response to requests with API Routes. Or have them run on a defined schedule with Scheduled Jobs.

create-order-in-erp.ts

sync-order-to-erp.ts

src > subscribers > sync-order-to-erp.ts

import {
type SubscriberConfig,
} from "@medusajs/framework"
import syncOrderToErp from "../workflows/sync-order-to-erp"
export default async function handleOrderPlaced({
event: { data },
container,
}) {
const orderService = container.resolve("order")
const order = await orderService.retrieve(id)
await syncOrderToErp(container).run({
input: {
order
},
})
}
export const config: SubscriberConfig = {
event: "order.placed",
}

Let’s talk

Ready to build your booking platform?

See how Medusa powers fully customizable booking experiences. From pricing to integrations to customer portals, build a system that fits your business - without the usual limitations.

Project dashboard