Build an HTTP REST API for Hotel Reservation¶
Overview¶
This use case demonstrates how to build a true RESTful API using WSO2 Integrator: BI that follows REST architectural constraints, including Hypermedia As The Engine Of Application State (HATEOAS). You will create a hotel room reservation service where users can browse locations, check room availability, make reservations, and complete payments all by following hypermedia links provided by the API at each step.
The API implements Richardson Maturity Model Level 3, making it self-descriptive and discoverable. Users only need to know one well-known entry point URL to navigate through the entire reservation workflow.
Why this use case¶
- Demonstrates building Level 3 REST APIs with proper hypermedia controls
- Shows how to implement discoverable APIs where clients follow server-provided links
- Illustrates proper HTTP method semantics (GET, POST, PUT, DELETE) and status codes
- Teaches creating self-descriptive APIs that require minimal external documentation
- Provides a real-world hotel reservation workflow
API workflow¶
GET /locations- Browse available resort locations (entry point)GET /locations/{id}/rooms- Check room availability at a locationPOST /reservations- Create a new reservationPUT /reservations/{id}- Modify an existing reservation (optional)DELETE /reservations/{id}- Cancel a reservation (optional)POST /payments/{id}- Complete payment and confirm reservation
Each response includes _links that guide users to the next possible actions, making the API self-navigating.
Prerequisites¶
Before you begin, make sure you have the following:
- Visual Studio Code: Install Visual Studio Code if you don't have it already.
- WSO2 Integrator: BI Extension: Install the WSO2 Integrator: BI extension. Refer to Install WSO2 Integrator: BI for detailed instructions.
Step 1: Create a new integration project¶
WSO2 Integrator: BI extension provides a low-code graphical environment to visually design, build, and deploy REST APIs using Ballerina.
- Launch VS Code and click the WSO2 Integrator: BI icon on the left sidebar.
- Click Create New Integration under the Get Started Quickly section.
- Enter the integration name as
HotelReservationAPI. - Select a location for your project directory.
- Click Create Integration to initialize the workspace.
Step 2: Define data types for the API¶
In this step, you'll define the structure of data that flows through your API locations, rooms, reservations, and payments. These types act as contracts between your API and its clients.
- In the Project Explorer, click Types and then + Add Type.
- Select JSON format and paste sample payloads to auto-generate types.
Create the data types¶
Type: Location
{
"name": "Alps Resort",
"id": "l1000",
"address": "123 Mountain Road, Switzerland"
}
Type: Room
{
"id": "r1000",
"category": "DELUXE",
"capacity": 5,
"wifi": true,
"status": "AVAILABLE",
"currency": "USD",
"price": 200.00,
"count": 3
}
Type: ReservationRequest
{
"reserveRooms": [
{"id": "r1000", "count": 2}
],
"startDate": "2025-08-01",
"endDate": "2025-08-03"
}
Type: ReservationReceipt
{
"id": "re1000",
"expiryDate": "2025-07-01",
"lastUpdated": "2025-06-29T13:01:30Z",
"currency": "USD",
"total": 400.00,
"state": "VALID"
}
Type: Payment
{
"cardNumber": "1234567890123456",
"expiryDate": "12/27",
"cvv": "123"
}
Step 3: Create the HTTP service¶
In this step, you'll create the HTTP service that will host all your REST API endpoints.
- In the design view, click + Add Artifact.
- Select HTTP Service under Integration as API.
-
Configure the service with the following settings:
- Service Base Path:
/hotel - Listener: Create new listener with port
8290 - Service Contract: Design from Scratch
- Service Base Path:
-
Click Create to generate the service.
Your service will be accessible at http://localhost:8290/hotel
Step 4: Add the locations resource (entry point)¶
This is the well-known URL, the only URL users need to know to start using your API. All other URLs will be discovered through hypermedia links.
- Click + Add Resource in the HTTP service.
-
Configure the resource with the following settings:
- HTTP Method: GET
- Resource Path:
locations - Return Type: Create a new type
Locationsas an array ofLocation
-
Click Save.
Step 5: Add the reservations resource¶
This resource creates a new reservation and provides links to edit, cancel, or complete payment.
- Click + Add Resource.
-
Configure with the following settings:
- HTTP Method: POST
- Resource Path:
reservations - Request Payload:
ReservationRequesttype - Return Type:
ReservationReceiptwith status201 Created
-
Click Save.
Step 6: Add edit and cancel reservation resources¶
These optional resources allow users to modify or cancel reservations before payment.
Edit reservation resource (PUT)¶
- Resource Path:
reservations/[string id] - Request Payload:
ReservationRequest - Return Type: Updated
ReservationReceiptwith links
Cancel reservation resource (DELETE)¶
- Resource Path:
reservations/[string id] - Return Status:
204 No Content - Error Response:
http:NotFoundfor invalid IDs
Step 7: Run and test the API¶
- Click the Run button in the BI extension.
- Wait for the service to start on port 8290.
Test the complete workflow¶
- Start at the entry point
curl http://localhost:8290/hotel/locations
Response includes link to rooms:
{
"locations": [...],
"_links": {
"room": {
"href": "/hotel/locations/{id}/rooms",
"methods": ["GET"]
}
}
}
- Follow the "room" link
curl "http://localhost:8290/hotel/locations/l1000/rooms?startDate=2025-08-01&endDate=2025-08-03"
Response includes link to make reservation:
{
"rooms": [...],
"_links": {
"reservation": {
"href": "/hotel/reservations",
"methods": ["POST"]
}
}
}
- Follow the "reservation" link
curl -X POST http://localhost:8290/hotel/reservations \
-H "Content-Type: application/json" \
-d '{
"reserveRooms": [{"id": "r1000", "count": 2}],
"startDate": "2025-08-01",
"endDate": "2025-08-03"
}'
Response includes links to cancel, edit, or pay:
{
"id": "re1000",
"total": 400.00,
"state": "VALID",
"_links": {
"cancel": {...},
"edit": {...},
"payment": {
"href": "/hotel/payments/re1000",
"methods": ["POST"]
}
}
}
- Follow the "payment" link to complete
curl -X POST http://localhost:8290/hotel/payments/re1000 \
-H "Content-Type: application/json" \
-d '{
"cardNumber": "1234567890123456",
"expiryDate": "12/27",
"cvv": "123"
}'
Response has no links (workflow complete):
{
"id": "p1000",
"total": 400.00,
"rooms": [{"id": "r1000", "status": "RESERVED"}]
}
Understand REST principles in this use case¶
Hypermedia as the engine of application state (HATEOAS)¶
The API uses hypermedia links (_links) to guide clients through the workflow:
- Self-descriptive: Each response tells you what actions are available next
- Discoverable: Clients don't need to memorize URL patterns
- Loosely coupled: Server can change URLs without breaking clients
- Evolvable: New features appear as new links
Addressable resources¶
Each entity has a unique URL
- Locations:
/hotel/locations - Rooms:
/hotel/locations/{id}/rooms - Reservations:
/hotel/reservations/{id} - Payments:
/hotel/payments/{id}
Uniform interface¶
Standard HTTP methods with consistent semantics
- GET: Safe and cacheable retrieves data without side effects
- POST: Creates new resources or triggers actions
- PUT: Updates existing resources idempotently
- DELETE: Removes resources
Stateless communication¶
Each request contains all necessary information. The server doesn't remember previous requests. Client state (like reservation details) is transferred with each request.
Domain-specific media type¶
The custom media type application/vnd.hotel.resort+json identifies this API's domain and helps clients understand the expected data structures.
Benefits of this REST approach¶
- No URL construction needed: Clients follow server-provided links instead of building URLs
- Self-documenting workflow: Links show available actions at each step
- Flexible evolution: Add new state transitions without breaking existing clients
- Reduced coupling: Clients aren't tied to specific URL patterns
- Similar to web browsing: Navigate through states like clicking links on a website
Summary¶
You've built a Richardson Maturity Model Level 3 REST API using WSO2 Integrator: BI that demonstrates:
- True REST architecture with hypermedia controls
- Self-descriptive API that guides users through workflows
- Proper HTTP semantics for all operations
- Discoverable design requiring only one well-known entry point
- Stateless, scalable architecture suitable for production use
This approach creates APIs that are as intuitive to use as websites, requiring minimal documentation beyond the entry point URL and business domain knowledge.