-
The most important decision here was how to prevent double bookings. To solve this problem we have ticket bookings in two phases:
- The user first reserves a ticket. We look for available (or cancelled) tickets in the DB and then "reserve" them in valkey by creating
<ticket_id>:<user_id>
pairs with a TTL (10 minutes). - The user then has to book the tickets within the TTL by calling /ticket/book/
- The user first reserves a ticket. We look for available (or cancelled) tickets in the DB and then "reserve" them in valkey by creating
-
The code base follows hexagonal architecture Hexagonal Architecture
-
Fault Tolerance is ensured by:
- Failing Gracefully in case of errors, keeping the state in the DB correct.
- Used transactions to ensure that the state of the DB does not change between queries.
-
Ensured the systems scalablity by doing the following things:
- I have applied indexes to speed up high priority queries.
- This monolith can be easily split up into microservices in the future.
- Its perfomance can be further improved by caching some heavy GET apis in valkey.
- JWT Bearer Token: Most endpoints require authentication via JWT token in the Authorization header
- Format:
Authorization: Bearer <jwt_token>
- Admin Role: Some endpoints require admin privileges
All errors follow this structure:
{
"category": "string",
"category_code": "string",
"msg": "string",
"error": "error_details" // optional
}
Description: Health check endpoint
Authentication: None required
Request: No body
Response:
{
"health": "ok",
"message": "Hello from booked!"
}
Status Codes: 200 OK
Description: Register a new user
Authentication: None required
Request Body:
{
"name": "string",
"email": "string",
"password": "string"
}
Response: No body (201 Created)
Status Codes:
- 201 Created - User registered successfully
- 400 Bad Request - Invalid JSON or validation error
- 500 Internal Server Error - System error
Possible Errors:
SYS-01
- JSON decode errorUSER-07
- Empty emailUSER-08
- Empty nameUSER-02
- Empty password
Description: Login user and get JWT token
Authentication: None required
Request Body:
{
"email": "string",
"password": "string"
}
Response:
{
"token": "string"
}
Status Codes:
- 200 OK - Login successful
- 400 Bad Request - Invalid JSON
- 401 Unauthorized - Invalid credentials
- 500 Internal Server Error - System error
Possible Errors:
SYS-01
- JSON decode errorUSER-03
- User not foundUSER-04
- Invalid password
Description: Get user's past bookings
Authentication: JWT required
Request: No body
Response:
[
{
"event_id": "string",
"event_name": "string",
"event_unix_time": 1234567890,
"event_address": "string",
"event_description": "string",
"event_latitude": 12.34, // optional
"event_longitude": 56.78, // optional
"number_of_tickets": 2,
"booking_unix_time": 1234567890
}
]
Status Codes:
- 200 OK - Bookings retrieved successfully
- 401 Unauthorized - Invalid or missing token
- 500 Internal Server Error - System error
Description: Create a new event (Admin only)
Authentication: JWT + Admin role required
Request Body:
{
"name": "string",
"unix_time": 1234567890,
"address": "string",
"description": "string",
"latitude": 12.34, // optional
"longitude": 56.78, // optional
"seat_count": 100
}
Response: No body (201 Created)
Status Codes:
- 201 Created - Event created successfully
- 400 Bad Request - Invalid JSON or validation error
- 401 Unauthorized - Invalid token or not admin
- 500 Internal Server Error - System error
Possible Errors:
SYS-01
- JSON decode errorEVENT-01
- Invalid seat countEVENT-04
- Invalid new event data
Description: Get paginated list of events
Authentication: None required
Query Parameters:
limit
(optional): Number of events to return (default: 10)timestamp
(optional): Unix timestamp for pagination
Response:
{
"next_time_to_fetch": 1234567890,
"events": [
{
"id": "string",
"name": "string",
"unix_time": 1234567890,
"address": "string",
"description": "string",
"seat_count": 100,
"available_seats_count": 50,
"latitude": 12.34, // optional
"longitude": 56.78 // optional
}
]
}
Status Codes:
- 200 OK - Events retrieved successfully
- 500 Internal Server Error - System error
Description: Delete an event (Admin only)
Authentication: JWT + Admin role required
Query Parameters:
id
: Event ID to delete
Response: No body (200 OK)
Status Codes:
- 200 OK - Event deleted successfully
- 400 Bad Request - Event not found
- 401 Unauthorized - Invalid token or not admin
- 500 Internal Server Error - System error
Possible Errors:
EVENT-03
- No event found
Description: Update an event (Admin only)
Authentication: JWT + Admin role required
Request Body:
{
"id": "string",
"name": "string", // optional
"unix_time": 1234567890, // optional
"address": "string", // optional
"description": "string", // optional
"latitude": 12.34, // optional
"longitude": 56.78, // optional
"seat_count": 100 // optional
}
Response: No body (201 Created)
Status Codes:
- 201 Created - Event updated successfully
- 400 Bad Request - Invalid JSON or validation error
- 401 Unauthorized - Invalid token or not admin
- 500 Internal Server Error - System error
Possible Errors:
SYS-01
- JSON decode errorEVENT-05
- Can't reduce seat count
Description: Reserve tickets for an event
Authentication: JWT required
Request Body:
{
"event_id": "string",
"count": 2
}
Response:
{
"ticket_ids": ["uuid1", "uuid2"]
}
Status Codes:
- 200 OK - Tickets reserved successfully
- 400 Bad Request - Invalid JSON or validation error
- 401 Unauthorized - Invalid token
- 500 Internal Server Error - System error
Possible Errors:
SYS-01
- JSON decode errorSYS-03
- Invalid UUID
Description: Book previously reserved tickets
Authentication: JWT required
Request Body:
{
"ticket_ids": ["uuid1", "uuid2"]
}
Response: No body (200 OK)
Status Codes:
- 200 OK - Tickets booked successfully
- 400 Bad Request - Invalid JSON or validation error
- 401 Unauthorized - Invalid token
- 500 Internal Server Error - System error
Possible Errors:
SYS-01
- JSON decode errorTICKET-02
- Ticket not reserved
Description: Cancel booked tickets
Authentication: JWT required
Request Body:
{
"event_id": "string",
"count": 2
}
Response: No body (200 OK)
Status Codes:
- 200 OK - Tickets cancelled successfully
- 400 Bad Request - Invalid JSON or validation error
- 401 Unauthorized - Invalid token
- 500 Internal Server Error - System error
Possible Errors:
SYS-01
- JSON decode errorSYS-03
- Invalid UUIDTICKET-01
- Too few ticketsTICKET-03
- Not your ticket
Description: Get total bookings analytics for all events, includes analytics like the number of tickets booked today and the capacity utilisation of the venue, the list is sorted by capacity utilsation (decreasing) indicating the most popular events.
Authentication: JWT + Admin role required
Request: No body
Response:
[
{
"event_id": "string",
"total_seats": 100,
"sold_tickets": 75,
"capacity_utilisation": 0.75,
"today_booked_tickets": 10
}
]
Status Codes:
- 200 OK - Analytics retrieved successfully
- 401 Unauthorized - Invalid token or not admin
- 500 Internal Server Error - System error
Description: Get cancellation rates for all events
Authentication: JWT + Admin role required
Request: No body
Response:
[
{
"event_id": "string",
"cancellation_rate": 0.15
}
]
Status Codes:
- 200 OK - Cancellation rates retrieved successfully
- 401 Unauthorized - Invalid token or not admin
- 500 Internal Server Error - System error
Description: Add user to event waitlist
Authentication: JWT required
Request Body:
{
"event_id": "string",
"count": 2
}
Response: No body (200 OK)
Status Codes:
- 200 OK - Added to waitlist successfully
- 400 Bad Request - Invalid JSON or validation error
- 401 Unauthorized - Invalid token
- 500 Internal Server Error - System error
Possible Errors:
SYS-01
- JSON decode errorSYS-03
- Invalid UUIDWAITLIST-01
- Already in waitlistWAITLIST-02
- Invalid waitlist count
SYS-01
- JSON decode errorSYS-02
- Unknown errorSYS-03
- Invalid UUID
USER-01
- Invalid user roleUSER-02
- Empty passwordUSER-03
- User not foundUSER-04
- Invalid passwordUSER-05
- JWT sign failureUSER-06
- Invalid tokenUSER-07
- Empty emailUSER-08
- Empty name
EVENT-01
- Invalid seat countEVENT-02
- Invalid event IDEVENT-03
- No event foundEVENT-04
- Invalid new eventEVENT-05
- Can't reduce seat count
TICKET-01
- Too few ticketsTICKET-02
- Ticket not reservedTICKET-03
- Not your ticket
WAITLIST-01
- Already in waitlistWAITLIST-02
- Invalid waitlist count
DB-01
- Database read errorDB-02
- Database write errorDB-03
- Database transaction error