Production-inspired REST API built with FastAPI, designed for secure room booking, conflict prevention, refund calculation, role-based authorization, and concurrent request handling.
CoWork API is a secure, multi-tenant backend service that powers a coworking space reservation platform.
The project allows organizations to manage rooms while enabling members to create, view, and cancel bookings under a strict set of business rules. The system focuses on correctness, predictable API behavior, and safe handling of concurrent requests.
Unlike a simple CRUD application, this project enforces real-world booking constraints including:
- preventing overlapping reservations
- enforcing booking quotas
- automatic refund calculation
- organization isolation
- role-based authorization
- JWT authentication
- booking reference generation
- pagination
- usage reporting
- CSV export
- concurrent request protection
The entire application is implemented as a RESTful API using FastAPI and follows a layered architecture that separates routers, services, authentication, persistence, and utility modules.
- π’ Multi-tenant organization support
- π JWT Authentication (Access + Refresh Tokens)
- π€ Role-based Authorization (Admin / Member)
- π Room Booking Management
- π« Conflict Detection
- π° Automatic Pricing
- π΅ Refund Calculation
- π Room Statistics
- π Usage Reports
- π CSV Export
- β‘ Pagination
- π Thread-safe Booking Operations
- π Docker Support
- π Interactive Swagger Documentation
- π§© Modular Service Architecture
The primary goal of this project is to implement a booking platform that satisfies a comprehensive business specification while maintaining a stable public API contract.
Special attention has been given to:
- Business Rule Enforcement
- API Consistency
- Concurrent Request Safety
- Security
- Data Integrity
- Clean Code Organization
- Predictable Error Handling
- Maintainability
- Organization registration
- Automatic organization creation
- Member onboarding
- JWT Access Token
- Refresh Token
- Token Rotation
- Logout with Token Revocation
- Create rooms
- List organization rooms
- Room availability lookup
- Live room statistics
- Create booking
- Booking validation
- Booking conflict detection
- Booking listing
- Booking details
- Booking cancellation
- Automatic pricing
- Booking reference generation
- Organization usage report
- CSV export
- Organization-wide booking visibility
- Revenue reporting
The project includes protections against several common backend consistency issues:
- Overlapping room reservations
- Duplicate booking references
- Duplicate refund creation
- Cross-room quota race conditions
- Concurrent booking conflicts
- Concurrent cancellation races
- Organization data leakage
This project was intentionally designed with correctness before complexity.
Instead of relying on unnecessary abstractions, the implementation emphasizes:
- explicit business rule enforcement
- predictable request lifecycle
- clear separation of responsibilities
- minimal API surface
- defensive validation
- readable service organization
The goal is to make the codebase understandable, maintainable, and easy to verify while preserving the required API contract.
The API provides everything required to support a coworking booking platform:
- User Authentication
- Organization Management
- Room Management
- Booking Engine
- Refund Engine
- Reporting
- Export
- Statistics
- Authorization
- Validation
- Pagination
- Concurrency Protection
while maintaining complete isolation between organizations.
| Category | Technology |
|---|---|
| Language | Python 3.11 |
| Framework | FastAPI |
| Database | SQLite |
| ORM | SQLAlchemy |
| Authentication | JWT |
| Validation | Pydantic |
| API Docs | Swagger UI |
| Containerization | Docker |
| Server | Uvicorn |
This README covers:
- Project Overview
- Architecture
- Folder Structure
- Installation
- Configuration
- Authentication Flow
- API Endpoints
- Business Rules
- Concurrency Strategy
- Error Handling
- Testing
- Deployment
- Future Improvements
Continue reading below for the complete documentation.
The application follows a layered architecture that separates responsibilities across routers, services, authentication, persistence, and utilities.
Client
β
βΌ
FastAPI Router Layer
β
ββββββββββββ΄βββββββββββ
β β
Authentication Business Logic
β β
βΌ βΌ
Services Layer Validation Layer
β β
ββββββββββββ¬βββββββββββ
βΌ
SQLAlchemy ORM
β
βΌ
SQLite Database
Each layer has a single responsibility:
| Layer | Responsibility |
|---|---|
| Routers | HTTP endpoints and request handling |
| Auth | JWT creation, verification and authorization |
| Services | Business logic and reusable operations |
| Models | Database entities |
| Schemas | Request/Response validation |
| Database | Session management |
| Utilities | Datetime helpers, caching, statistics |
app/
β
βββ main.py
βββ database.py
βββ models.py
βββ schemas.py
βββ auth.py
βββ config.py
βββ errors.py
βββ timeutils.py
β
βββ routers/
β βββ auth.py
β βββ rooms.py
β βββ bookings.py
β βββ admin.py
β
βββ services/
β βββ cache.py
β βββ export.py
β βββ notifications.py
β βββ ratelimit.py
β βββ reference.py
β βββ refunds.py
β βββ stats.py
β
βββ requirements.txt
Contains all REST API endpoints.
Each router focuses on one bounded domain.
- Authentication
- Rooms
- Bookings
- Administration
Routers contain minimal business logic and delegate complex operations to services.
Contains reusable business components.
Examples:
- Booking reference generation
- Refund calculation
- CSV export
- Statistics
- Rate limiting
- Notifications
- Cache helpers
Keeping these operations isolated makes the routers significantly cleaner.
Responsible for
- JWT generation
- JWT validation
- Refresh token handling
- Token revocation
- Role verification
Defines every request and response model using Pydantic.
Examples:
- RegisterRequest
- LoginRequest
- RoomCreateRequest
- BookingCreateRequest
Validation happens before requests reach the business logic.
Defines SQLAlchemy ORM models.
Current entities include:
- User
- Room
- Booking
- RefundLog
Initializes the SQLAlchemy engine, session factory, and database connection.
The project currently uses SQLite for simplicity and portability.
Every request follows the same lifecycle.
HTTP Request
β
βΌ
FastAPI Router
β
Authentication
β
Authorization
β
Validation
β
Business Rules
β
Database
β
Response Serialization
β
HTTP Response
This predictable pipeline keeps responsibilities separated and simplifies debugging.
Register
β
Login
β
Access Token
Refresh Token
β
Bearer Authentication
β
Protected Endpoints
β
Logout
β
Access Token Revoked
Create Booking
β
Validate Request
β
Validate Datetimes
β
Validate Room
β
Rate Limit Check
β
Quota Check
β
Conflict Detection
β
Price Calculation
β
Reference Generation
β
Persist Booking
β
Update Statistics
β
Invalidate Cache
β
Return Booking
Cancel Booking
β
Ownership Check
β
Booking Lock
β
Refund Calculation
β
Refund Log
β
Update Booking Status
β
Update Statistics
β
Invalidate Cache
β
Return Refund
Several endpoints perform state-changing operations.
To preserve correctness during concurrent requests, lightweight in-memory synchronization is used.
Current synchronization points include:
- Room-level booking lock
- User-level quota lock
- Booking-level cancellation lock
- Reference code generation lock
These guards ensure business rules remain consistent even when multiple requests arrive simultaneously.
Every organization owns its own resources.
The application guarantees that:
- Members cannot access another organization's rooms.
- Admins only manage their own organization.
- Reports are organization scoped.
- Room availability is organization scoped.
- Booking visibility is organization scoped.
Every database query involving protected resources applies organization filtering before returning data.
Although this project uses SQLite for the challenge, the architecture intentionally keeps the database layer isolated.
Migrating to PostgreSQL or MySQL would primarily require updating the SQLAlchemy configuration rather than changing application logic.
The service-oriented design also allows additional features such as email notifications, payment gateways, or distributed caching to be integrated with minimal changes.
Before running the project, ensure you have:
- Python 3.11+
- Docker Desktop (recommended)
- Git
- pip
git clone https://github.com/<your-username>/<repository>.git
cd <repository>Build and start the application.
docker compose up --buildRun in detached mode.
docker compose up -dStop containers.
docker compose downRebuild after code changes.
docker compose up --buildCreate a virtual environment.
Windows
python -m venv .venv
.venv\Scripts\activateLinux / macOS
python -m venv .venv
source .venv/bin/activateInstall dependencies.
pip install -r requirements.txtRun FastAPI.
uvicorn app.main:app --reloadServer
http://localhost:8000
Swagger UI
http://localhost:8000/docs
OpenAPI Schema
http://localhost:8000/openapi.json
The project currently uses a lightweight configuration suitable for the hackathon environment.
Main configuration includes:
- JWT Secret
- Token expiration
- Database URL
- SQLite configuration
Future deployments can externalize these values using environment variables.
Current database engine:
SQLite
ORM:
SQLAlchemy
Tables are created automatically during application startup.
No manual migration step is required.
Protected endpoints require a Bearer token.
Example
Authorization: Bearer <access_token>
Authentication flow:
Register
β
Login
β
Receive Tokens
β
Call Protected APIs
β
Logout
β
Token Revoked
Swagger UI
/docs
OpenAPI JSON
/openapi.json
Both are automatically generated from FastAPI.
git clone ...
docker compose up --build
Open:
http://localhost:8000/docs
Register
β
Login
β
Copy Access Token
β
Authorize
β
Test EndpointsRun Docker
docker compose upStop Docker
docker compose downRebuild
docker compose up --buildView Logs
docker compose logs -fGit Status
git statusGit Diff
git diff- Register organization
- Login
- Create room
- Create booking
- List bookings
- Booking detail
- Cancel booking
- Refresh token
- Logout
- Usage report
- Export CSV
The API follows REST principles and returns JSON responses.
Validation errors use FastAPI's validation mechanism, while application-specific errors follow the documented error contract.
The project is designed to be deterministic and preserve the public API contract defined by the challenge specification.
The API uses JSON Web Tokens (JWT) for stateless authentication.
Two token types are issued after a successful login:
| Token | Purpose |
|---|---|
| Access Token | Authenticate API requests |
| Refresh Token | Obtain a new access token |
The access token is supplied in the Authorization header:
Authorization: Bearer <access_token>Every protected endpoint validates:
- Token signature
- Token expiration
- Token type
- Token revocation status
- Organization
- User role
Register
β
βΌ
Login
β
βΌ
Access Token
Refresh Token
β
βΌ
Protected API
β
βΌ
Logout
β
βΌ
Access Token Revoked
β
βΌ
Refresh Token
β
βΌ
New Access Token
Two roles exist within the platform.
Administrators are allowed to
- Create rooms
- View organization reports
- Export booking data
- Access organization bookings
- View room statistics
- Cancel bookings inside their organization
Members are allowed to
- Login
- View rooms
- Create bookings
- View their bookings
- Cancel their own bookings
- Check room availability
Register
β
Login
β
Receive Tokens
β
API Requests
β
Logout
β
Access Token Invalid
β
Refresh
β
New Access Token
Refresh tokens are single-use and cannot be reused after a successful refresh.
Access tokens become invalid immediately after logout.
POST /auth/register
Request
{
"org_name": "Acme",
"username": "alice",
"password": "password123"
}Response
{
"user_id": 1,
"org_id": 1,
"username": "alice",
"role": "admin"
}POST /auth/login
Request
{
"org_name": "Acme",
"username": "alice",
"password": "password123"
}Response
{
"access_token": "...",
"refresh_token": "...",
"token_type": "bearer"
}POST /auth/refresh
Request
{
"refresh_token": "..."
}Returns a fresh access token.
POST /auth/logout
Revokes the presented access token.
GET /rooms
Returns every room belonging to the caller's organization.
POST /rooms
Request
{
"name": "Conference Room",
"capacity": 12,
"hourly_rate_cents": 2500
}Validation:
- name must not be empty
- capacity > 0
- hourly_rate_cents > 0
GET /rooms/{room_id}/availability
Query Parameter
date=YYYY-MM-DD
Returns all confirmed busy intervals for the selected day.
GET /rooms/{room_id}/stats
Response
{
"room_id": 1,
"total_confirmed_bookings": 15,
"total_revenue_cents": 30000
}POST /bookings
Request
{
"room_id": 1,
"start_time": "2026-07-10T10:00:00Z",
"end_time": "2026-07-10T12:00:00Z"
}Business rules enforced:
- Future booking only
- Whole-hour duration
- Duration between 1β8 hours
- No room conflicts
- User quota enforcement
- Rate limiting
- Price calculation
- Reference generation
GET /bookings?page=1&limit=10
Returns paginated bookings ordered by start time.
GET /bookings/{id}
Returns booking information together with refund history.
POST /bookings/{id}/cancel
Automatically computes refund based on cancellation timing.
Response
{
"id": 1,
"status": "cancelled",
"refund_percent": 50,
"refund_amount_cents": 1000
}GET /admin/usage-report
Provides room-wise booking and revenue statistics for a date range.
GET /admin/export
Supports:
- room filtering
- organization-wide export
- personal export
| Code | Meaning |
|---|---|
| INVALID_CREDENTIALS | Login failed |
| ROOM_CONFLICT | Room already booked |
| QUOTA_EXCEEDED | User booking limit reached |
| RATE_LIMITED | Too many booking attempts |
| ROOM_NOT_FOUND | Room unavailable |
| BOOKING_NOT_FOUND | Booking unavailable |
| FORBIDDEN | Permission denied |
| ALREADY_CANCELLED | Booking already cancelled |
| INVALID_BOOKING_WINDOW | Invalid booking request |
| UNAUTHORIZED | Invalid or expired token |
The API preserves a stable error contract across all endpoints to ensure predictable client behavior.
The implementation strictly follows the challenge specification and preserves the required API contract.
- Bookings must start in the future.
- Booking duration must be between 1 and 8 hours.
- Only whole-hour bookings are allowed.
- Room conflicts are not permitted.
- Booking price is calculated automatically.
- Members may hold at most 3 active bookings within the quota window.
- Booking requests are rate limited.
- Every booking receives a unique reference code.
Refund percentage depends on cancellation timing.
| Time Before Start | Refund |
|---|---|
| β₯ 24 Hours | 100% |
| β₯ 1 Hour | 50% |
| < 1 Hour | 0% |
Each cancelled booking generates exactly one refund record.
Members can:
- Create bookings
- View their own bookings
- Cancel their own bookings
Administrators can:
- Create rooms
- View organization reports
- Export booking data
- Manage organization resources
Every request is scoped to the authenticated user's organization.
No endpoint exposes another organization's:
- Rooms
- Bookings
- Reports
- Statistics
The implementation favors correctness and maintainability.
Key design principles include:
- Layered architecture
- Stateless authentication
- Explicit validation
- Clear separation of concerns
- Business logic isolated into services
- Predictable error handling
- Minimal API surface
- Thread-safe critical operations
Several endpoints modify shared resources.
To preserve business rules under concurrent requests, lightweight synchronization is used.
Protected operations include:
- Booking creation
- Booking cancellation
- User booking quota
- Booking reference generation
This prevents:
- Duplicate bookings
- Double refunds
- Quota races
- Duplicate reference codes
The API uses consistent JSON error responses.
Example:
{
"detail": "Room already booked",
"code": "ROOM_CONFLICT"
}Framework validation errors follow FastAPI's standard response format.
The public API contract is preserved throughout development.
No changes were introduced to:
- Endpoint paths
- Request schemas
- Response schemas
- Status codes
- Error codes
- Authentication format
This ensures compatibility with automated black-box grading.