# 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 number - `search` (string): Search by name or description - `company_type` (string): Filter by type (manufacturer, operator, designer, supplier, contractor) - `location_id` (UUID): Filter by headquarters location - `ordering` (string): Sort field (prefix with `-` for descending) **Example:** ```bash 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:** ```json { "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 number - `search` (string): Search by model name - `manufacturer_id` (UUID): Filter by manufacturer - `model_type` (string): Filter by model type - `ordering` (string): Sort field **Example:** ```bash curl "http://localhost:8000/api/v1/ride-models/?manufacturer_id=&model_type=coaster_model" ``` #### Get Ride Model ``` GET /api/v1/ride-models/{model_id} ``` #### Create Ride Model ``` POST /api/v1/ride-models/ ``` **Request Body:** ```json { "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 number - `search` (string): Search by park name - `park_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 operator - `ordering` (string): Sort field **Example:** ```bash 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 latitude - `longitude` (float, required): Center point longitude - `radius` (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:** ```bash curl "http://localhost:8000/api/v1/parks/nearby/?latitude=28.385233&longitude=-81.563874&radius=100" ``` #### Create Park ``` POST /api/v1/parks/ ``` **Request Body:** ```json { "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 number - `search` (string): Search by ride name - `park_id` (UUID): Filter by park - `ride_category` (string): Filter by category (roller_coaster, flat_ride, water_ride, dark_ride, transport_ride, other) - `status` (string): Filter by status - `is_coaster` (bool): Filter for roller coasters only - `manufacturer_id` (UUID): Filter by manufacturer - `ordering` (string): Sort field **Example:** ```bash 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 feet - `min_speed` (float): Minimum speed in mph **Example:** ```bash 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:** ```json { "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 ```json { "id": "uuid", "name": "Entity Name", "created": "2025-01-01T00:00:00Z", "modified": "2025-01-01T00:00:00Z", ... } ``` #### Paginated List ```json { "items": [...], "count": 100, "next": "http://api/endpoint/?page=2", "previous": null } ``` ### Error Responses #### 400 Bad Request ```json { "detail": "Invalid input", "errors": [ { "field": "name", "message": "This field is required" } ] } ``` #### 404 Not Found ```json { "detail": "Entity not found" } ``` #### 500 Internal Server Error ```json { "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: ```json { "latitude": 28.385233, "longitude": -81.563874 } ``` --- ## Testing the API ### Using curl ```bash # 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 1. Start the development server: ```bash cd django python manage.py runserver ``` 2. Open your browser to: ``` http://localhost:8000/api/v1/docs ``` 3. 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: 1. Check the interactive documentation at `/api/v1/docs` 2. Review this guide 3. Check the POSTGIS_SETUP.md for geographic features 4. 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