10 KiB
ThrillWiki REST API Guide
Phase 2B: REST API Development - Complete
This guide provides comprehensive documentation for the ThrillWiki REST API v1.
Overview
The ThrillWiki API provides programmatic access to amusement park, ride, and company data. It uses django-ninja for fast, modern REST API implementation with automatic OpenAPI documentation.
Base URL
- Local Development:
http://localhost:8000/api/v1/ - Production:
https://your-domain.com/api/v1/
Documentation
- Interactive API Docs:
/api/v1/docs - OpenAPI Schema:
/api/v1/openapi.json
Features
Implemented in Phase 2B
✅ Full CRUD Operations for all entities ✅ Filtering & Search on all list endpoints ✅ Pagination (50 items per page) ✅ Geographic Search for parks (dual-mode: SQLite + PostGIS) ✅ Automatic OpenAPI/Swagger Documentation ✅ Pydantic Schema Validation ✅ Related Data (automatic joins and annotations) ✅ Error Handling with detailed error responses
Coming in Phase 2C
- JWT Token Authentication
- Role-based Permissions
- Rate Limiting
- Caching
- Webhooks
Authentication
Current Status: Authentication placeholders are in place, but not yet enforced.
- Read Operations (GET): Public access
- Write Operations (POST, PUT, PATCH, DELETE): Will require authentication (JWT tokens)
Endpoints
System Endpoints
Health Check
GET /api/v1/health
Returns API health status.
API Information
GET /api/v1/info
Returns API metadata and statistics.
Companies
Companies represent manufacturers, operators, designers, and other entities in the amusement industry.
List Companies
GET /api/v1/companies/
Query Parameters:
page(int): Page numbersearch(string): Search by name or descriptioncompany_type(string): Filter by type (manufacturer, operator, designer, supplier, contractor)location_id(UUID): Filter by headquarters locationordering(string): Sort field (prefix with-for descending)
Example:
curl "http://localhost:8000/api/v1/companies/?search=B%26M&ordering=-park_count"
Get Company
GET /api/v1/companies/{company_id}
Create Company
POST /api/v1/companies/
Request Body:
{
"name": "Bolliger & Mabillard",
"description": "Swiss roller coaster manufacturer",
"company_types": ["manufacturer"],
"founded_date": "1988-01-01",
"website": "https://www.bolliger-mabillard.com"
}
Update Company
PUT /api/v1/companies/{company_id}
PATCH /api/v1/companies/{company_id}
Delete Company
DELETE /api/v1/companies/{company_id}
Get Company Parks
GET /api/v1/companies/{company_id}/parks
Returns all parks operated by the company.
Get Company Rides
GET /api/v1/companies/{company_id}/rides
Returns all rides manufactured by the company.
Ride Models
Ride models represent specific ride types from manufacturers.
List Ride Models
GET /api/v1/ride-models/
Query Parameters:
page(int): Page numbersearch(string): Search by model namemanufacturer_id(UUID): Filter by manufacturermodel_type(string): Filter by model typeordering(string): Sort field
Example:
curl "http://localhost:8000/api/v1/ride-models/?manufacturer_id=<uuid>&model_type=coaster_model"
Get Ride Model
GET /api/v1/ride-models/{model_id}
Create Ride Model
POST /api/v1/ride-models/
Request Body:
{
"name": "Wing Coaster",
"manufacturer_id": "uuid-here",
"model_type": "coaster_model",
"description": "Winged seating roller coaster",
"typical_height": 164.0,
"typical_speed": 55.0
}
Update Ride Model
PUT /api/v1/ride-models/{model_id}
PATCH /api/v1/ride-models/{model_id}
Delete Ride Model
DELETE /api/v1/ride-models/{model_id}
Get Model Installations
GET /api/v1/ride-models/{model_id}/installations
Returns all rides using this model.
Parks
Parks represent theme parks, amusement parks, water parks, and FECs.
List Parks
GET /api/v1/parks/
Query Parameters:
page(int): Page numbersearch(string): Search by park namepark_type(string): Filter by type (theme_park, amusement_park, water_park, family_entertainment_center, traveling_park, zoo, aquarium)status(string): Filter by status (operating, closed, sbno, under_construction, planned)operator_id(UUID): Filter by operatorordering(string): Sort field
Example:
curl "http://localhost:8000/api/v1/parks/?status=operating&park_type=theme_park"
Get Park
GET /api/v1/parks/{park_id}
Find Nearby Parks (Geographic Search)
GET /api/v1/parks/nearby/
Query Parameters:
latitude(float, required): Center point latitudelongitude(float, required): Center point longituderadius(float): Search radius in kilometers (default: 50)limit(int): Maximum results (default: 50)
Geographic Modes:
- PostGIS (Production): Accurate distance-based search using
location_point - SQLite (Local Dev): Bounding box approximation using
latitude/longitude
Example:
curl "http://localhost:8000/api/v1/parks/nearby/?latitude=28.385233&longitude=-81.563874&radius=100"
Create Park
POST /api/v1/parks/
Request Body:
{
"name": "Six Flags Magic Mountain",
"park_type": "theme_park",
"status": "operating",
"latitude": 34.4239,
"longitude": -118.5971,
"opening_date": "1971-05-29",
"website": "https://www.sixflags.com/magicmountain"
}
Update Park
PUT /api/v1/parks/{park_id}
PATCH /api/v1/parks/{park_id}
Delete Park
DELETE /api/v1/parks/{park_id}
Get Park Rides
GET /api/v1/parks/{park_id}/rides
Returns all rides at the park.
Rides
Rides represent individual rides and roller coasters.
List Rides
GET /api/v1/rides/
Query Parameters:
page(int): Page numbersearch(string): Search by ride namepark_id(UUID): Filter by parkride_category(string): Filter by category (roller_coaster, flat_ride, water_ride, dark_ride, transport_ride, other)status(string): Filter by statusis_coaster(bool): Filter for roller coasters onlymanufacturer_id(UUID): Filter by manufacturerordering(string): Sort field
Example:
curl "http://localhost:8000/api/v1/rides/?is_coaster=true&status=operating"
List Roller Coasters Only
GET /api/v1/rides/coasters/
Additional Query Parameters:
min_height(float): Minimum height in feetmin_speed(float): Minimum speed in mph
Example:
curl "http://localhost:8000/api/v1/rides/coasters/?min_height=200&min_speed=70"
Get Ride
GET /api/v1/rides/{ride_id}
Create Ride
POST /api/v1/rides/
Request Body:
{
"name": "Steel Vengeance",
"park_id": "uuid-here",
"ride_category": "roller_coaster",
"is_coaster": true,
"status": "operating",
"manufacturer_id": "uuid-here",
"height": 205.0,
"speed": 74.0,
"length": 5740.0,
"inversions": 4,
"opening_date": "2018-05-05"
}
Update Ride
PUT /api/v1/rides/{ride_id}
PATCH /api/v1/rides/{ride_id}
Delete Ride
DELETE /api/v1/rides/{ride_id}
Response Formats
Success Responses
Single Entity
{
"id": "uuid",
"name": "Entity Name",
"created": "2025-01-01T00:00:00Z",
"modified": "2025-01-01T00:00:00Z",
...
}
Paginated List
{
"items": [...],
"count": 100,
"next": "http://api/endpoint/?page=2",
"previous": null
}
Error Responses
400 Bad Request
{
"detail": "Invalid input",
"errors": [
{
"field": "name",
"message": "This field is required"
}
]
}
404 Not Found
{
"detail": "Entity not found"
}
500 Internal Server Error
{
"detail": "Internal server error",
"code": "server_error"
}
Data Types
UUID
All entity IDs use UUID format:
"550e8400-e29b-41d4-a716-446655440000"
Dates
ISO 8601 format (YYYY-MM-DD):
"2025-01-01"
Timestamps
ISO 8601 format with timezone:
"2025-01-01T12:00:00Z"
Coordinates
Latitude/Longitude as decimal degrees:
{
"latitude": 28.385233,
"longitude": -81.563874
}
Testing the API
Using curl
# Get API info
curl http://localhost:8000/api/v1/info
# List companies
curl http://localhost:8000/api/v1/companies/
# Search parks
curl "http://localhost:8000/api/v1/parks/?search=Six+Flags"
# Find nearby parks
curl "http://localhost:8000/api/v1/parks/nearby/?latitude=28.385&longitude=-81.563&radius=50"
Using the Interactive Docs
-
Start the development server:
cd django python manage.py runserver -
Open your browser to:
http://localhost:8000/api/v1/docs -
Explore and test all endpoints interactively!
Geographic Features
SQLite Mode (Local Development)
Uses simple latitude/longitude fields with bounding box approximation:
- Stores coordinates as
DecimalField - Geographic search uses bounding box calculation
- Less accurate but works without PostGIS
PostGIS Mode (Production)
Uses advanced geographic features:
- Stores coordinates as
PointField(geography type) - Accurate distance-based queries
- Supports spatial indexing
- Full GIS capabilities
Switching Between Modes
The API automatically detects the database backend and uses the appropriate method. No code changes needed!
Next Steps
Phase 2C: Admin Interface Enhancements
- Enhanced Django admin for all entities
- Bulk operations
- Advanced filtering
- Custom actions
Phase 3: Frontend Integration
- React/Next.js frontend
- Real-time updates
- Interactive maps
- Rich search interface
Phase 4: Advanced Features
- JWT authentication
- API rate limiting
- Caching strategies
- Webhooks
- WebSocket support
Support
For issues or questions about the API:
- Check the interactive documentation at
/api/v1/docs - Review this guide
- Check the POSTGIS_SETUP.md for geographic features
- Refer to the main README.md for project setup
Version History
- v1.0.0 (Phase 2B): Initial REST API implementation
- Full CRUD for all entities
- Filtering and search
- Geographic queries
- Pagination
- OpenAPI documentation