mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-24 13:11:09 -05:00
- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols. - Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage. - Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
1514 lines
41 KiB
Markdown
1514 lines
41 KiB
Markdown
# ThrillWiki API Documentation v1
|
|
## Complete Frontend Developer Reference
|
|
|
|
**Base URL**: `/api/v1/`
|
|
**Authentication**: JWT Bearer tokens
|
|
**Content-Type**: `application/json`
|
|
|
|
---
|
|
|
|
## 🔑 Authentication Requirements
|
|
|
|
### JWT Authentication
|
|
Most endpoints require authentication via JWT Bearer tokens. Include the token in the `Authorization` header:
|
|
|
|
```bash
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
### Token Lifetime
|
|
- **Access Token**: 15 minutes (configurable via `JWT_ACCESS_TOKEN_LIFETIME_MINUTES`)
|
|
- **Refresh Token**: 7 days (configurable via `JWT_REFRESH_TOKEN_LIFETIME_DAYS`)
|
|
|
|
### Unauthenticated Access
|
|
The following endpoints allow unauthenticated access:
|
|
- `GET /parks/` - List parks
|
|
- `GET /parks/<pk>/` - Park details
|
|
- `GET /rides/` - List rides
|
|
- `GET /rides/<pk>/` - Ride details
|
|
- `GET /parks/<pk>/photos/` - Park photos list
|
|
- `GET /rides/<pk>/photos/` - Ride photos list
|
|
- `POST /auth/login/` - User login
|
|
- `POST /auth/signup/` - User registration
|
|
- `POST /auth/password/reset/` - Password reset request
|
|
- `GET /auth/social/providers/` - Available social providers
|
|
|
|
---
|
|
|
|
## ⏱️ Rate Limiting
|
|
|
|
Rate limits are enforced per user/IP to prevent abuse:
|
|
|
|
| User Type | Limit |
|
|
|-----------|-------|
|
|
| Anonymous | 60 requests/minute |
|
|
| Authenticated | 1000 requests/hour |
|
|
|
|
### Rate Limit Headers
|
|
Responses include rate limit information in headers:
|
|
```
|
|
X-RateLimit-Limit: 1000
|
|
X-RateLimit-Remaining: 995
|
|
X-RateLimit-Reset: 1703347200
|
|
```
|
|
|
|
### Rate Limit Exceeded Response
|
|
```json
|
|
{
|
|
"error": "Request was throttled",
|
|
"error_code": "RATE_LIMIT_EXCEEDED",
|
|
"detail": "Expected available in 60 seconds."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📄 Pagination
|
|
|
|
List endpoints use page-based pagination:
|
|
|
|
### Query Parameters
|
|
| Parameter | Type | Default | Max | Description |
|
|
|-----------|------|---------|-----|-------------|
|
|
| `page` | int | 1 | - | Page number |
|
|
| `page_size` | int | 20 | 100 | Results per page |
|
|
|
|
### Paginated Response Format
|
|
```json
|
|
{
|
|
"count": 150,
|
|
"next": "https://api.thrillwiki.com/api/v1/parks/?page=2",
|
|
"previous": null,
|
|
"results": [...]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔐 Authentication Endpoints (`/api/v1/auth/`)
|
|
|
|
### POST `/auth/login/` - User Login
|
|
|
|
Authenticate a user and receive JWT tokens.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"username": "johndoe",
|
|
"password": "securepassword123"
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/login/ \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"username": "johndoe", "password": "securepassword123"}'
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
|
|
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
|
|
"user": {
|
|
"id": 42,
|
|
"username": "johndoe",
|
|
"email": "johndoe@example.com",
|
|
"display_name": "John Doe",
|
|
"avatar_url": "https://imagedelivery.net/xxx/avatar.jpg"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Response (400 Bad Request):**
|
|
```json
|
|
{
|
|
"error": "Invalid credentials",
|
|
"error_code": "INVALID_CREDENTIALS",
|
|
"details": {
|
|
"non_field_errors": ["Unable to log in with provided credentials."]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/auth/signup/` - User Registration
|
|
|
|
Register a new user account. Email verification is required before full access.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"username": "newuser",
|
|
"email": "newuser@example.com",
|
|
"password1": "ComplexPass123!",
|
|
"password2": "ComplexPass123!"
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/signup/ \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"username": "newuser", "email": "newuser@example.com", "password1": "ComplexPass123!", "password2": "ComplexPass123!"}'
|
|
```
|
|
|
|
**Success Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Verification email sent. Please check your inbox.",
|
|
"user": {
|
|
"id": 43,
|
|
"username": "newuser",
|
|
"email": "newuser@example.com"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Response (400 Bad Request):**
|
|
```json
|
|
{
|
|
"error": "Validation failed",
|
|
"error_code": "VALIDATION_ERROR",
|
|
"details": {
|
|
"username": ["A user with that username already exists."],
|
|
"password1": ["This password is too common."]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/auth/logout/` - User Logout
|
|
|
|
Logout the current user and blacklist the refresh token.
|
|
|
|
**Authentication:** Required
|
|
|
|
**Request Body (optional):**
|
|
```json
|
|
{
|
|
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/logout/ \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"refresh": "<refresh_token>"}'
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Successfully logged out."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET `/auth/user/` - Get Current User
|
|
|
|
Retrieve the authenticated user's information.
|
|
|
|
**Authentication:** Required
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X GET https://api.thrillwiki.com/api/v1/auth/user/ \
|
|
-H "Authorization: Bearer <access_token>"
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"id": 42,
|
|
"username": "johndoe",
|
|
"email": "johndoe@example.com",
|
|
"display_name": "John Doe",
|
|
"date_joined": "2024-01-15T10:30:00Z",
|
|
"is_active": true,
|
|
"avatar_url": "https://imagedelivery.net/xxx/avatar.jpg"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/auth/status/` - Check Authentication Status
|
|
|
|
Check if the current request is authenticated.
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/status/ \
|
|
-H "Authorization: Bearer <access_token>"
|
|
```
|
|
|
|
**Authenticated Response (200 OK):**
|
|
```json
|
|
{
|
|
"authenticated": true,
|
|
"user": {
|
|
"id": 42,
|
|
"username": "johndoe"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Unauthenticated Response (200 OK):**
|
|
```json
|
|
{
|
|
"authenticated": false
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/auth/password/reset/` - Request Password Reset
|
|
|
|
Request a password reset email.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "johndoe@example.com"
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/password/reset/ \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email": "johndoe@example.com"}'
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Password reset email sent."
|
|
}
|
|
```
|
|
|
|
> **Note:** For security, this endpoint always returns success, regardless of whether the email exists.
|
|
|
|
---
|
|
|
|
### POST `/auth/password/change/` - Change Password
|
|
|
|
Change the authenticated user's password.
|
|
|
|
**Authentication:** Required
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"old_password": "currentpassword",
|
|
"new_password1": "NewComplexPass123!",
|
|
"new_password2": "NewComplexPass123!"
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/password/change/ \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"old_password": "currentpassword", "new_password1": "NewComplexPass123!", "new_password2": "NewComplexPass123!"}'
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Password changed successfully."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/auth/token/refresh/` - Refresh Access Token
|
|
|
|
Obtain a new access token using a refresh token.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/token/refresh/ \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"refresh": "<refresh_token>"}'
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
|
|
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
|
|
}
|
|
```
|
|
|
|
> **Note:** Refresh tokens are rotated on each use. The old refresh token is blacklisted.
|
|
|
|
---
|
|
|
|
### GET `/auth/social/providers/` - Get Social Providers
|
|
|
|
List available social authentication providers.
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X GET https://api.thrillwiki.com/api/v1/auth/social/providers/
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
[
|
|
{
|
|
"provider": "google",
|
|
"name": "Google",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"provider": "discord",
|
|
"name": "Discord",
|
|
"enabled": true
|
|
}
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
### Email Verification Endpoints
|
|
- **GET** `/auth/verify-email/<token>/` - Verify email with token
|
|
- **POST** `/auth/resend-verification/` - Resend email verification
|
|
|
|
### Social Authentication Endpoints
|
|
- **GET** `/auth/social/providers/available/` - Get available social providers list
|
|
- **GET** `/auth/social/connected/` - Get user's connected social providers (auth required)
|
|
- **POST** `/auth/social/connect/<provider>/` - Connect social provider (auth required)
|
|
- **POST** `/auth/social/disconnect/<provider>/` - Disconnect social provider (auth required)
|
|
- **GET** `/auth/social/status/` - Get comprehensive social auth status (auth required)
|
|
|
|
---
|
|
|
|
## 🏞️ Parks API Endpoints (`/api/v1/parks/`)
|
|
|
|
### GET `/parks/hybrid/` - List Parks with Hybrid Filtering
|
|
|
|
Retrieve parks with intelligent hybrid filtering strategy. This endpoint provides optimal performance by selecting between database and client-side filtering based on the query.
|
|
|
|
**Authentication:** Optional
|
|
|
|
**Query Parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `search` | string | Search by park name |
|
|
| `status` | string | Filter by status (OPERATING, CLOSED_PERM, UNDER_CONSTRUCTION) |
|
|
| `continent` | string | Filter by continent code |
|
|
| `country` | string | Filter by country code |
|
|
| `state` | string | Filter by state/province |
|
|
| `operator_slug` | string | Filter by operator slug |
|
|
| `rating_min` | float | Minimum rating (0-10) |
|
|
| `rating_max` | float | Maximum rating (0-10) |
|
|
| `opening_year_min` | int | Minimum opening year |
|
|
| `opening_year_max` | int | Maximum opening year |
|
|
| `coaster_count_min` | int | Minimum roller coaster count |
|
|
| `coaster_count_max` | int | Maximum roller coaster count |
|
|
| `offset` | int | Pagination offset for progressive loading |
|
|
| `ordering` | string | Sort field (name, -name, rating, -rating) |
|
|
|
|
**curl Example:**
|
|
```bash
|
|
# List operating parks in North America with rating >= 7
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/parks/hybrid/?status=OPERATING&continent=NA&rating_min=7"
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"parks": [
|
|
{
|
|
"id": 1,
|
|
"name": "Cedar Point",
|
|
"slug": "cedar-point",
|
|
"description": "The Roller Coaster Capital of the World",
|
|
"status": "OPERATING",
|
|
"park_type": "THEME",
|
|
"opening_year": 1870,
|
|
"location": {
|
|
"continent": "NA",
|
|
"country": "US",
|
|
"state": "OH",
|
|
"city": "Sandusky",
|
|
"latitude": 41.4784,
|
|
"longitude": -82.6775
|
|
},
|
|
"operator": {
|
|
"id": 5,
|
|
"name": "Cedar Fair",
|
|
"slug": "cedar-fair"
|
|
},
|
|
"statistics": {
|
|
"ride_count": 72,
|
|
"roller_coaster_count": 17,
|
|
"average_rating": 9.2
|
|
},
|
|
"image_url": "https://imagedelivery.net/xxx/park-main.jpg"
|
|
}
|
|
],
|
|
"total_count": 45,
|
|
"has_more": true,
|
|
"strategy": "database",
|
|
"filter_metadata": {
|
|
"statuses": ["OPERATING", "CLOSED_PERM", "UNDER_CONSTRUCTION"],
|
|
"continents": ["NA", "EU", "AS", "SA", "OC", "AF"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET `/parks/<pk>/` - Get Park Details
|
|
|
|
Retrieve detailed information about a specific park by ID or slug.
|
|
|
|
**Authentication:** Optional
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X GET https://api.thrillwiki.com/api/v1/parks/cedar-point/
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"name": "Cedar Point",
|
|
"slug": "cedar-point",
|
|
"description": "The Roller Coaster Capital of the World, featuring world-class thrill rides.",
|
|
"status": "OPERATING",
|
|
"park_type": "THEME",
|
|
"opening_year": 1870,
|
|
"website": "https://www.cedarpoint.com",
|
|
"location": {
|
|
"address": "1 Cedar Point Drive",
|
|
"city": "Sandusky",
|
|
"state": "OH",
|
|
"country": "US",
|
|
"continent": "NA",
|
|
"postal_code": "44870",
|
|
"latitude": 41.4784,
|
|
"longitude": -82.6775
|
|
},
|
|
"operator": {
|
|
"id": 5,
|
|
"name": "Cedar Fair",
|
|
"slug": "cedar-fair"
|
|
},
|
|
"property_owner": {
|
|
"id": 5,
|
|
"name": "Cedar Fair",
|
|
"slug": "cedar-fair"
|
|
},
|
|
"statistics": {
|
|
"ride_count": 72,
|
|
"roller_coaster_count": 17,
|
|
"flat_ride_count": 32,
|
|
"water_ride_count": 8,
|
|
"average_rating": 9.2,
|
|
"review_count": 1523
|
|
},
|
|
"images": {
|
|
"primary": "https://imagedelivery.net/xxx/park-main.jpg",
|
|
"gallery": [
|
|
"https://imagedelivery.net/xxx/park-1.jpg",
|
|
"https://imagedelivery.net/xxx/park-2.jpg"
|
|
]
|
|
},
|
|
"created_at": "2024-01-01T00:00:00Z",
|
|
"updated_at": "2024-12-15T14:30:00Z"
|
|
}
|
|
```
|
|
|
|
**Error Response (404 Not Found):**
|
|
```json
|
|
{
|
|
"error": "Park not found",
|
|
"error_code": "NOT_FOUND",
|
|
"details": {
|
|
"message": "No park exists with the given identifier."
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/parks/` - Create Park
|
|
|
|
Create a new park entry.
|
|
|
|
**Authentication:** Required
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"name": "New Theme Park",
|
|
"description": "An exciting new theme park opening soon.",
|
|
"status": "UNDER_CONSTRUCTION",
|
|
"park_type": "THEME",
|
|
"opening_year": 2025,
|
|
"operator_id": 5,
|
|
"location": {
|
|
"city": "Orlando",
|
|
"state": "FL",
|
|
"country": "US",
|
|
"latitude": 28.3772,
|
|
"longitude": -81.5707
|
|
}
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/parks/ \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name": "New Theme Park", "status": "UNDER_CONSTRUCTION", "park_type": "THEME"}'
|
|
```
|
|
|
|
**Success Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": 156,
|
|
"name": "New Theme Park",
|
|
"slug": "new-theme-park",
|
|
"status": "UNDER_CONSTRUCTION"
|
|
},
|
|
"message": "Park created successfully."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/parks/<park_pk>/photos/` - Upload Park Photo
|
|
|
|
Upload a photo for a park.
|
|
|
|
**Authentication:** Required
|
|
**Content-Type:** `multipart/form-data`
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/parks/1/photos/ \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-F "image=@/path/to/photo.jpg" \
|
|
-F "caption=Beautiful entrance view" \
|
|
-F "photo_type=GENERAL"
|
|
```
|
|
|
|
**Success Response (201 Created):**
|
|
```json
|
|
{
|
|
"id": 523,
|
|
"image_url": "https://imagedelivery.net/xxx/photo.jpg",
|
|
"caption": "Beautiful entrance view",
|
|
"photo_type": "GENERAL",
|
|
"is_primary": false,
|
|
"is_approved": false,
|
|
"uploaded_by": {
|
|
"id": 42,
|
|
"username": "johndoe"
|
|
},
|
|
"created_at": "2024-12-20T10:30:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/parks/<park_pk>/photos/bulk_approve/` - Bulk Approve Photos (Admin)
|
|
|
|
Bulk approve or reject multiple photos at once.
|
|
|
|
**Authentication:** Required (Staff only)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"photo_ids": [523, 524, 525],
|
|
"approve": true
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/parks/1/photos/bulk_approve/ \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"photo_ids": [523, 524, 525], "approve": true}'
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "3 photos approved successfully.",
|
|
"processed": 3
|
|
}
|
|
```
|
|
|
|
**Error Response (403 Forbidden):**
|
|
```json
|
|
{
|
|
"error": "Permission denied",
|
|
"error_code": "FORBIDDEN",
|
|
"details": {
|
|
"message": "Staff privileges required for bulk operations."
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET `/parks/filter-metadata/` - Get Filter Metadata
|
|
|
|
Retrieve available filter options and value ranges for park filtering.
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X GET https://api.thrillwiki.com/api/v1/parks/filter-metadata/
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"categorical": {
|
|
"statuses": [
|
|
{"value": "OPERATING", "label": "Operating", "count": 2500},
|
|
{"value": "CLOSED_PERM", "label": "Permanently Closed", "count": 850},
|
|
{"value": "UNDER_CONSTRUCTION", "label": "Under Construction", "count": 45}
|
|
],
|
|
"park_types": [
|
|
{"value": "THEME", "label": "Theme Park", "count": 1200},
|
|
{"value": "AMUSEMENT", "label": "Amusement Park", "count": 1800}
|
|
],
|
|
"continents": [
|
|
{"value": "NA", "label": "North America", "count": 1100},
|
|
{"value": "EU", "label": "Europe", "count": 900}
|
|
]
|
|
},
|
|
"ranges": {
|
|
"opening_year": {"min": 1843, "max": 2025},
|
|
"rating": {"min": 0, "max": 10},
|
|
"ride_count": {"min": 0, "max": 150},
|
|
"coaster_count": {"min": 0, "max": 20}
|
|
},
|
|
"total_count": 3395
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Additional Parks Endpoints
|
|
|
|
#### Search & Filtering
|
|
- **GET** `/parks/filter-options/` - Get available filter options (legacy)
|
|
- **GET** `/parks/search/companies/?q=<query>` - Search companies/operators
|
|
- **GET** `/parks/search-suggestions/?q=<query>` - Get park search suggestions
|
|
|
|
#### Park Photos
|
|
- **GET** `/parks/<park_pk>/photos/` - List park photos
|
|
- **GET** `/parks/<park_pk>/photos/<id>/` - Get park photo details
|
|
- **PATCH** `/parks/<park_pk>/photos/<id>/` - Update park photo (auth required)
|
|
- **DELETE** `/parks/<park_pk>/photos/<id>/` - Delete park photo (auth required)
|
|
- **POST** `/parks/<park_pk>/photos/<id>/set_primary/` - Set photo as primary (auth required)
|
|
- **GET** `/parks/<park_pk>/photos/stats/` - Get park photo statistics
|
|
|
|
#### Park Settings
|
|
- **GET** `/parks/<pk>/image-settings/` - Get park image settings
|
|
- **POST** `/parks/<pk>/image-settings/` - Update park image settings
|
|
|
|
---
|
|
|
|
## 🎢 Rides API Endpoints (`/api/v1/rides/`)
|
|
|
|
### GET `/rides/hybrid/` - List Rides with Hybrid Filtering
|
|
|
|
Retrieve rides with intelligent filtering. Similar to parks, this endpoint uses hybrid strategy for optimal performance.
|
|
|
|
**Authentication:** Optional
|
|
|
|
**Query Parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `search` | string | Search by ride name |
|
|
| `park` | string | Filter by park slug |
|
|
| `category` | string | Filter by category (RC, DR, FR, WR, TR, OT) |
|
|
| `manufacturer_slug` | string | Filter by manufacturer |
|
|
| `status` | string | Filter by status |
|
|
| `speed_min` | float | Minimum speed (mph) |
|
|
| `speed_max` | float | Maximum speed (mph) |
|
|
| `height_min` | float | Minimum height (ft) |
|
|
| `height_max` | float | Maximum height (ft) |
|
|
| `opening_year_min` | int | Minimum opening year |
|
|
| `opening_year_max` | int | Maximum opening year |
|
|
| `ordering` | string | Sort field |
|
|
|
|
**curl Example:**
|
|
```bash
|
|
# List roller coasters at Cedar Point
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/rides/hybrid/?park=cedar-point&category=RC"
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"rides": [
|
|
{
|
|
"id": 42,
|
|
"name": "Steel Vengeance",
|
|
"slug": "steel-vengeance",
|
|
"category": "RC",
|
|
"category_display": "Roller Coaster",
|
|
"status": "OPERATING",
|
|
"opening_year": 2018,
|
|
"park": {
|
|
"id": 1,
|
|
"name": "Cedar Point",
|
|
"slug": "cedar-point"
|
|
},
|
|
"manufacturer": {
|
|
"id": 10,
|
|
"name": "Rocky Mountain Construction",
|
|
"slug": "rocky-mountain-construction"
|
|
},
|
|
"statistics": {
|
|
"height_ft": 205,
|
|
"speed_mph": 74,
|
|
"length_ft": 5740,
|
|
"inversions": 4,
|
|
"average_rating": 9.8
|
|
},
|
|
"image_url": "https://imagedelivery.net/xxx/ride.jpg"
|
|
}
|
|
],
|
|
"total_count": 17,
|
|
"has_more": false,
|
|
"strategy": "database"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET `/rides/<pk>/` - Get Ride Details
|
|
|
|
Retrieve detailed information about a specific ride.
|
|
|
|
**Authentication:** Optional
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X GET https://api.thrillwiki.com/api/v1/rides/steel-vengeance/
|
|
```
|
|
|
|
**Success Response (200 OK):**
|
|
```json
|
|
{
|
|
"id": 42,
|
|
"name": "Steel Vengeance",
|
|
"slug": "steel-vengeance",
|
|
"description": "A record-breaking hybrid coaster built on the bones of Mean Streak.",
|
|
"category": "RC",
|
|
"category_display": "Roller Coaster",
|
|
"status": "OPERATING",
|
|
"opening_year": 2018,
|
|
"park": {
|
|
"id": 1,
|
|
"name": "Cedar Point",
|
|
"slug": "cedar-point"
|
|
},
|
|
"manufacturer": {
|
|
"id": 10,
|
|
"name": "Rocky Mountain Construction",
|
|
"slug": "rocky-mountain-construction"
|
|
},
|
|
"ride_model": {
|
|
"id": 15,
|
|
"name": "IBox Track Conversion",
|
|
"slug": "ibox-track-conversion"
|
|
},
|
|
"specifications": {
|
|
"height_ft": 205,
|
|
"drop_ft": 200,
|
|
"speed_mph": 74,
|
|
"length_ft": 5740,
|
|
"duration_seconds": 150,
|
|
"inversions": 4,
|
|
"capacity_per_hour": 1200,
|
|
"min_height_inches": 52
|
|
},
|
|
"statistics": {
|
|
"average_rating": 9.8,
|
|
"review_count": 2847,
|
|
"ranking_position": 1
|
|
},
|
|
"images": {
|
|
"primary": "https://imagedelivery.net/xxx/ride-main.jpg",
|
|
"gallery": [
|
|
"https://imagedelivery.net/xxx/ride-1.jpg"
|
|
]
|
|
},
|
|
"created_at": "2024-01-01T00:00:00Z",
|
|
"updated_at": "2024-12-15T14:30:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/rides/` - Create Ride
|
|
|
|
Create a new ride entry.
|
|
|
|
**Authentication:** Required
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"name": "New Coaster",
|
|
"category": "RC",
|
|
"status": "UNDER_CONSTRUCTION",
|
|
"park_id": 1,
|
|
"manufacturer_id": 10,
|
|
"opening_year": 2025,
|
|
"specifications": {
|
|
"height_ft": 300,
|
|
"speed_mph": 90
|
|
}
|
|
}
|
|
```
|
|
|
|
**curl Example:**
|
|
```bash
|
|
curl -X POST https://api.thrillwiki.com/api/v1/rides/ \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name": "New Coaster", "category": "RC", "park_id": 1}'
|
|
```
|
|
|
|
**Success Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": 1523,
|
|
"name": "New Coaster",
|
|
"slug": "new-coaster",
|
|
"category": "RC"
|
|
},
|
|
"message": "Ride created successfully."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Ride Category Codes
|
|
|
|
| Code | Category |
|
|
|------|----------|
|
|
| `RC` | Roller Coaster |
|
|
| `DR` | Dark Ride |
|
|
| `FR` | Flat Ride |
|
|
| `WR` | Water Ride |
|
|
| `TR` | Transport Ride |
|
|
| `OT` | Other |
|
|
|
|
---
|
|
|
|
### Additional Rides Endpoints
|
|
|
|
#### Search & Filtering
|
|
- **GET** `/rides/filter-options/` - Get available filter options
|
|
- **GET** `/rides/search/companies/?q=<query>` - Search ride companies
|
|
- **GET** `/rides/search/ride-models/?q=<query>` - Search ride models
|
|
- **GET** `/rides/search-suggestions/?q=<query>` - Get ride search suggestions
|
|
- **GET** `/rides/hybrid/filter-metadata/` - Get ride filter metadata
|
|
|
|
#### Ride Photos
|
|
- **GET** `/rides/<ride_pk>/photos/` - List ride photos
|
|
- **POST** `/rides/<ride_pk>/photos/` - Upload ride photo (auth required)
|
|
- **GET** `/rides/<ride_pk>/photos/<id>/` - Get ride photo details
|
|
- **PATCH** `/rides/<ride_pk>/photos/<id>/` - Update ride photo (auth required)
|
|
- **DELETE** `/rides/<ride_pk>/photos/<id>/` - Delete ride photo (auth required)
|
|
- **POST** `/rides/<ride_pk>/photos/<id>/set_primary/` - Set photo as primary (auth required)
|
|
|
|
#### Ride Manufacturers
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/` - List manufacturer's rides
|
|
|
|
#### Ride Settings
|
|
- **GET** `/rides/<pk>/image-settings/` - Get ride image settings
|
|
- **POST** `/rides/<pk>/image-settings/` - Update ride image settings
|
|
|
|
---
|
|
|
|
## 👤 User Accounts API (`/api/v1/accounts/`)
|
|
|
|
### User Management (Admin)
|
|
- **DELETE** `/accounts/users/<user_id>/delete/` - Delete user while preserving submissions
|
|
- **GET** `/accounts/users/<user_id>/deletion-check/` - Check user deletion eligibility
|
|
|
|
### Self-Service Account Management
|
|
- **POST** `/accounts/delete-account/request/` - Request account deletion
|
|
- **POST** `/accounts/delete-account/verify/` - Verify account deletion
|
|
- **POST** `/accounts/delete-account/cancel/` - Cancel account deletion
|
|
|
|
### User Profile Management
|
|
- **GET** `/accounts/profile/` - Get user profile
|
|
- **PATCH** `/accounts/profile/account/` - Update user account info
|
|
- **PATCH** `/accounts/profile/update/` - Update user profile
|
|
|
|
### User Preferences
|
|
- **GET** `/accounts/preferences/` - Get user preferences
|
|
- **PATCH** `/accounts/preferences/update/` - Update user preferences
|
|
- **PATCH** `/accounts/preferences/theme/` - Update theme preference
|
|
|
|
### Settings Management
|
|
- **GET** `/accounts/settings/notifications/` - Get notification settings
|
|
- **PATCH** `/accounts/settings/notifications/update/` - Update notification settings
|
|
- **GET** `/accounts/settings/privacy/` - Get privacy settings
|
|
- **PATCH** `/accounts/settings/privacy/update/` - Update privacy settings
|
|
- **GET** `/accounts/settings/security/` - Get security settings
|
|
- **PATCH** `/accounts/settings/security/update/` - Update security settings
|
|
|
|
### User Statistics & Lists
|
|
- **GET** `/accounts/statistics/` - Get user statistics
|
|
- **GET** `/accounts/top-lists/` - Get user's top lists
|
|
- **POST** `/accounts/top-lists/create/` - Create new top list
|
|
- **PATCH** `/accounts/top-lists/<list_id>/` - Update top list
|
|
- **DELETE** `/accounts/top-lists/<list_id>/delete/` - Delete top list
|
|
|
|
### Notifications
|
|
- **GET** `/accounts/notifications/` - Get user notifications
|
|
- **POST** `/accounts/notifications/mark-read/` - Mark notifications as read
|
|
- **GET** `/accounts/notification-preferences/` - Get notification preferences
|
|
- **PATCH** `/accounts/notification-preferences/update/` - Update notification preferences
|
|
|
|
### Avatar Management
|
|
- **POST** `/accounts/profile/avatar/upload/` - Upload avatar
|
|
- **POST** `/accounts/profile/avatar/save/` - Save avatar image
|
|
- **DELETE** `/accounts/profile/avatar/delete/` - Delete avatar
|
|
|
|
---
|
|
|
|
## 🗺️ Maps API (`/api/v1/maps/`)
|
|
|
|
### Location Data
|
|
- **GET** `/maps/locations/` - Get map locations data
|
|
- **GET** `/maps/locations/<location_type>/<location_id>/` - Get location details
|
|
- **GET** `/maps/search/` - Search locations on map
|
|
- **GET** `/maps/bounds/` - Query locations within bounds
|
|
|
|
### Map Services
|
|
- **GET** `/maps/stats/` - Get map service statistics
|
|
- **GET** `/maps/cache/` - Get map cache information
|
|
- **POST** `/maps/cache/invalidate/` - Invalidate map cache
|
|
|
|
---
|
|
|
|
## 🔍 Core Search API (`/api/v1/core/`)
|
|
|
|
### Entity Search
|
|
- **GET** `/core/entities/search/` - Fuzzy search for entities
|
|
- **GET** `/core/entities/not-found/` - Handle entity not found
|
|
- **GET** `/core/entities/suggestions/` - Quick entity suggestions
|
|
|
|
---
|
|
|
|
## 📧 Email API (`/api/v1/email/`)
|
|
|
|
### Email Services
|
|
- **POST** `/email/send/` - Send email
|
|
|
|
---
|
|
|
|
## 📜 History API (`/api/v1/history/`)
|
|
|
|
### Park History
|
|
- **GET** `/history/parks/<park_slug>/` - Get park history
|
|
- **GET** `/history/parks/<park_slug>/detail/` - Get detailed park history
|
|
|
|
### Ride History
|
|
- **GET** `/history/parks/<park_slug>/rides/<ride_slug>/` - Get ride history
|
|
- **GET** `/history/parks/<park_slug>/rides/<ride_slug>/detail/` - Get detailed ride history
|
|
|
|
### Unified Timeline
|
|
- **GET** `/history/timeline/` - Get unified history timeline
|
|
|
|
---
|
|
|
|
## 📈 System & Analytics APIs
|
|
|
|
### Health Checks
|
|
- **GET** `/api/v1/health/` - Comprehensive health check
|
|
- **GET** `/api/v1/health/simple/` - Simple health check
|
|
- **GET** `/api/v1/health/performance/` - Performance metrics
|
|
|
|
### Trending & Discovery
|
|
- **GET** `/api/v1/trending/` - Get trending content
|
|
- **GET** `/api/v1/new-content/` - Get new content
|
|
- **POST** `/api/v1/trending/calculate/` - Trigger trending calculation
|
|
|
|
### Statistics
|
|
- **GET** `/api/v1/stats/` - Get system statistics
|
|
- **POST** `/api/v1/stats/recalculate/` - Recalculate statistics
|
|
|
|
### Reviews
|
|
- **GET** `/api/v1/reviews/latest/` - Get latest reviews
|
|
|
|
### Rankings
|
|
- **GET** `/api/v1/rankings/` - Get ride rankings with filtering
|
|
- **GET** `/api/v1/rankings/<ride_slug>/` - Get detailed ranking for specific ride
|
|
- **GET** `/api/v1/rankings/<ride_slug>/history/` - Get ranking history for ride
|
|
- **GET** `/api/v1/rankings/<ride_slug>/comparisons/` - Get head-to-head comparisons
|
|
- **GET** `/api/v1/rankings/statistics/` - Get ranking system statistics
|
|
- **POST** `/api/v1/rankings/calculate/` - Trigger ranking calculation (admin)
|
|
|
|
#### Rankings Filtering Parameters:
|
|
- **category**: Filter by ride category (RC, DR, FR, WR, TR, OT)
|
|
- **min_riders**: Minimum number of mutual riders required
|
|
- **park**: Filter by park slug
|
|
- **ordering**: Order results (rank, -rank, winning_percentage, -winning_percentage)
|
|
|
|
---
|
|
|
|
## 🛡️ Moderation API (`/api/v1/moderation/`)
|
|
|
|
### Moderation Reports
|
|
- **GET** `/moderation/reports/` - List all moderation reports
|
|
- **POST** `/moderation/reports/` - Create new moderation report
|
|
- **GET** `/moderation/reports/<id>/` - Get specific report details
|
|
- **PUT** `/moderation/reports/<id>/` - Update moderation report
|
|
- **PATCH** `/moderation/reports/<id>/` - Partial update report
|
|
- **DELETE** `/moderation/reports/<id>/` - Delete moderation report
|
|
- **POST** `/moderation/reports/<id>/assign/` - Assign report to moderator
|
|
- **POST** `/moderation/reports/<id>/resolve/` - Resolve moderation report
|
|
- **GET** `/moderation/reports/stats/` - Get report statistics
|
|
|
|
### Moderation Queue
|
|
- **GET** `/moderation/queue/` - List moderation queue items
|
|
- **POST** `/moderation/queue/` - Create queue item
|
|
- **GET** `/moderation/queue/<id>/` - Get specific queue item
|
|
- **PUT** `/moderation/queue/<id>/` - Update queue item
|
|
- **PATCH** `/moderation/queue/<id>/` - Partial update queue item
|
|
- **DELETE** `/moderation/queue/<id>/` - Delete queue item
|
|
- **POST** `/moderation/queue/<id>/assign/` - Assign queue item to moderator
|
|
- **POST** `/moderation/queue/<id>/unassign/` - Unassign queue item
|
|
- **POST** `/moderation/queue/<id>/complete/` - Complete queue item
|
|
- **GET** `/moderation/queue/my_queue/` - Get current user's queue items
|
|
|
|
### Moderation Actions
|
|
- **GET** `/moderation/actions/` - List all moderation actions
|
|
- **POST** `/moderation/actions/` - Create new moderation action
|
|
- **GET** `/moderation/actions/<id>/` - Get specific action details
|
|
- **PUT** `/moderation/actions/<id>/` - Update moderation action
|
|
- **PATCH** `/moderation/actions/<id>/` - Partial update action
|
|
- **DELETE** `/moderation/actions/<id>/` - Delete moderation action
|
|
- **POST** `/moderation/actions/<id>/deactivate/` - Deactivate action
|
|
- **GET** `/moderation/actions/active/` - Get active moderation actions
|
|
- **GET** `/moderation/actions/expired/` - Get expired moderation actions
|
|
|
|
### Bulk Operations
|
|
- **GET** `/moderation/bulk-operations/` - List bulk moderation operations
|
|
- **POST** `/moderation/bulk-operations/` - Create bulk operation
|
|
- **GET** `/moderation/bulk-operations/<id>/` - Get bulk operation details
|
|
- **PUT** `/moderation/bulk-operations/<id>/` - Update bulk operation
|
|
- **PATCH** `/moderation/bulk-operations/<id>/` - Partial update operation
|
|
- **DELETE** `/moderation/bulk-operations/<id>/` - Delete bulk operation
|
|
- **POST** `/moderation/bulk-operations/<id>/cancel/` - Cancel bulk operation
|
|
- **POST** `/moderation/bulk-operations/<id>/retry/` - Retry failed operation
|
|
- **GET** `/moderation/bulk-operations/<id>/logs/` - Get operation logs
|
|
- **GET** `/moderation/bulk-operations/running/` - Get running operations
|
|
|
|
### User Moderation
|
|
- **GET** `/moderation/users/<id>/` - Get user moderation profile
|
|
- **POST** `/moderation/users/<id>/moderate/` - Take moderation action against user
|
|
- **GET** `/moderation/users/search/` - Search users for moderation
|
|
- **GET** `/moderation/users/stats/` - Get user moderation statistics
|
|
|
|
---
|
|
|
|
## 🏗️ Ride Manufacturers & Models (`/api/v1/rides/manufacturers/<manufacturer_slug>/`)
|
|
|
|
### Ride Models
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/` - List ride models by manufacturer
|
|
- **POST** `/rides/manufacturers/<manufacturer_slug>/` - Create new ride model
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/` - Get ride model details
|
|
- **PATCH** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/` - Update ride model
|
|
- **DELETE** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/` - Delete ride model
|
|
|
|
### Model Search & Filtering
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/search/` - Search ride models
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/filter-options/` - Get filter options
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/stats/` - Get manufacturer statistics
|
|
|
|
### Model Variants
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/variants/` - List model variants
|
|
- **POST** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/variants/` - Create variant
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/variants/<id>/` - Get variant details
|
|
- **PATCH** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/variants/<id>/` - Update variant
|
|
- **DELETE** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/variants/<id>/` - Delete variant
|
|
|
|
### Technical Specifications
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/technical-specs/` - List technical specs
|
|
- **POST** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/technical-specs/` - Create technical spec
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/technical-specs/<id>/` - Get spec details
|
|
- **PATCH** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/technical-specs/<id>/` - Update spec
|
|
- **DELETE** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/technical-specs/<id>/` - Delete spec
|
|
|
|
### Model Photos
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/photos/` - List model photos
|
|
- **POST** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/photos/` - Upload model photo
|
|
- **GET** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/photos/<id>/` - Get photo details
|
|
- **PATCH** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/photos/<id>/` - Update photo
|
|
- **DELETE** `/rides/manufacturers/<manufacturer_slug>/<ride_model_slug>/photos/<id>/` - Delete photo
|
|
|
|
---
|
|
|
|
## 🖼️ Media Management
|
|
|
|
### Cloudflare Images
|
|
- **ALL** `/api/v1/cloudflare-images/` - Cloudflare Images toolkit endpoints
|
|
|
|
---
|
|
|
|
## 📚 API Documentation
|
|
|
|
### Interactive Documentation
|
|
- **GET** `/api/schema/` - OpenAPI schema
|
|
- **GET** `/api/docs/` - Swagger UI documentation
|
|
- **GET** `/api/redoc/` - ReDoc documentation
|
|
|
|
---
|
|
|
|
## 🔧 Common Request/Response Patterns
|
|
|
|
### Authentication Headers
|
|
```javascript
|
|
headers: {
|
|
'Authorization': 'Bearer <access_token>',
|
|
'Content-Type': 'application/json'
|
|
}
|
|
```
|
|
|
|
### Pagination Response
|
|
```json
|
|
{
|
|
"count": 100,
|
|
"next": "https://api.thrillwiki.com/api/v1/endpoint/?page=2",
|
|
"previous": null,
|
|
"results": [...]
|
|
}
|
|
```
|
|
|
|
### Success Response Format
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Operation completed successfully",
|
|
"data": {...}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## ❌ Error Response Reference
|
|
|
|
All error responses follow a consistent format with appropriate HTTP status codes.
|
|
|
|
### Error Response Structure
|
|
```json
|
|
{
|
|
"error": "Human-readable error message",
|
|
"error_code": "MACHINE_READABLE_CODE",
|
|
"details": {
|
|
"field_name": ["Specific field error message"]
|
|
},
|
|
"suggestions": ["Suggestion for resolution"]
|
|
}
|
|
```
|
|
|
|
### HTTP Status Codes
|
|
|
|
| Code | Meaning | When Used |
|
|
|------|---------|-----------|
|
|
| 400 | Bad Request | Invalid request body, missing required fields, validation errors |
|
|
| 401 | Unauthorized | Missing or invalid authentication token |
|
|
| 403 | Forbidden | Authenticated but lacks permission for the action |
|
|
| 404 | Not Found | Requested resource doesn't exist |
|
|
| 405 | Method Not Allowed | HTTP method not supported for endpoint |
|
|
| 409 | Conflict | Resource conflict (e.g., duplicate entry) |
|
|
| 422 | Unprocessable Entity | Request understood but semantically incorrect |
|
|
| 429 | Too Many Requests | Rate limit exceeded |
|
|
| 500 | Internal Server Error | Unexpected server error |
|
|
|
|
### Common Error Codes
|
|
|
|
#### Authentication Errors (401)
|
|
```json
|
|
{
|
|
"error": "Authentication credentials were not provided",
|
|
"error_code": "AUTHENTICATION_REQUIRED"
|
|
}
|
|
```
|
|
|
|
```json
|
|
{
|
|
"error": "Token is invalid or expired",
|
|
"error_code": "INVALID_TOKEN",
|
|
"details": {
|
|
"token_type": "access",
|
|
"message": "Token has expired"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Authorization Errors (403)
|
|
```json
|
|
{
|
|
"error": "Permission denied",
|
|
"error_code": "FORBIDDEN",
|
|
"details": {
|
|
"message": "You do not have permission to perform this action.",
|
|
"required_permission": "is_staff"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Validation Errors (400)
|
|
```json
|
|
{
|
|
"error": "Validation failed",
|
|
"error_code": "VALIDATION_ERROR",
|
|
"details": {
|
|
"name": ["This field is required."],
|
|
"email": ["Enter a valid email address."],
|
|
"password1": [
|
|
"This password is too short. It must contain at least 8 characters.",
|
|
"This password is too common."
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Not Found Errors (404)
|
|
```json
|
|
{
|
|
"error": "Park not found",
|
|
"error_code": "NOT_FOUND",
|
|
"details": {
|
|
"resource": "Park",
|
|
"identifier": "nonexistent-park-slug"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Rate Limit Errors (429)
|
|
```json
|
|
{
|
|
"error": "Request was throttled",
|
|
"error_code": "RATE_LIMIT_EXCEEDED",
|
|
"detail": "Expected available in 45 seconds.",
|
|
"retry_after": 45
|
|
}
|
|
```
|
|
|
|
#### Conflict Errors (409)
|
|
```json
|
|
{
|
|
"error": "Resource already exists",
|
|
"error_code": "DUPLICATE_ENTRY",
|
|
"details": {
|
|
"field": "username",
|
|
"message": "A user with this username already exists."
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📝 Key Data Models
|
|
|
|
### User
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `id` | int | Unique identifier |
|
|
| `username` | string | Unique username |
|
|
| `email` | string | Email address |
|
|
| `display_name` | string | Display name |
|
|
| `date_joined` | datetime | Account creation date |
|
|
| `is_active` | boolean | Account active status |
|
|
| `avatar_url` | string | Avatar image URL |
|
|
|
|
### Park
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `id` | int | Unique identifier |
|
|
| `name` | string | Park name |
|
|
| `slug` | string | URL-friendly identifier |
|
|
| `description` | string | Park description |
|
|
| `status` | enum | OPERATING, CLOSED_PERM, UNDER_CONSTRUCTION |
|
|
| `park_type` | enum | THEME, AMUSEMENT, WATER, etc. |
|
|
| `opening_year` | int | Year park opened |
|
|
| `location` | object | Location details (city, country, coordinates) |
|
|
| `operator` | object | Operating company |
|
|
|
|
### Ride
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `id` | int | Unique identifier |
|
|
| `name` | string | Ride name |
|
|
| `slug` | string | URL-friendly identifier |
|
|
| `category` | enum | RC, DR, FR, WR, TR, OT |
|
|
| `status` | enum | OPERATING, CLOSED_PERM, etc. |
|
|
| `park` | object | Parent park |
|
|
| `manufacturer` | object | Ride manufacturer |
|
|
| `opening_year` | int | Year ride opened |
|
|
| `specifications` | object | Height, speed, length, etc. |
|
|
|
|
### Photo
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `id` | int | Unique identifier |
|
|
| `image_url` | string | Full image URL |
|
|
| `caption` | string | Photo caption |
|
|
| `photo_type` | enum | GENERAL, ENTRANCE, RIDE, etc. |
|
|
| `is_primary` | boolean | Primary photo flag |
|
|
| `is_approved` | boolean | Moderation approval status |
|
|
| `uploaded_by` | object | User who uploaded |
|
|
| `created_at` | datetime | Upload timestamp |
|
|
|
|
---
|
|
|
|
## 📖 Complete curl Examples
|
|
|
|
### Full Authentication Flow
|
|
|
|
```bash
|
|
# 1. Register a new account
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/signup/ \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"username": "coasterenthusiast",
|
|
"email": "coaster@example.com",
|
|
"password1": "MySecurePass123!",
|
|
"password2": "MySecurePass123!"
|
|
}'
|
|
|
|
# 2. Login to get tokens
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/login/ \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"username": "coasterenthusiast", "password": "MySecurePass123!"}' \
|
|
| jq -r '.access' > access_token.txt
|
|
|
|
# 3. Use the access token for authenticated requests
|
|
ACCESS_TOKEN=$(cat access_token.txt)
|
|
curl -X GET https://api.thrillwiki.com/api/v1/auth/user/ \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN"
|
|
|
|
# 4. Refresh the token when it expires
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/token/refresh/ \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"refresh": "<refresh_token>"}'
|
|
|
|
# 5. Logout
|
|
curl -X POST https://api.thrillwiki.com/api/v1/auth/logout/ \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"refresh": "<refresh_token>"}'
|
|
```
|
|
|
|
### Listing and Filtering Parks
|
|
|
|
```bash
|
|
# List all operating parks
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/parks/hybrid/?status=OPERATING"
|
|
|
|
# Search for parks by name
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/parks/hybrid/?search=disney"
|
|
|
|
# Filter by location and rating
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/parks/hybrid/?continent=NA&country=US&rating_min=8"
|
|
|
|
# Paginate through results
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/parks/hybrid/?offset=20"
|
|
|
|
# Get detailed park information
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/parks/cedar-point/"
|
|
```
|
|
|
|
### Working with Rides
|
|
|
|
```bash
|
|
# List all roller coasters at a specific park
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/rides/hybrid/?park=cedar-point&category=RC"
|
|
|
|
# Filter by speed and height
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/rides/hybrid/?speed_min=70&height_min=200"
|
|
|
|
# Get ride details
|
|
curl -X GET "https://api.thrillwiki.com/api/v1/rides/steel-vengeance/"
|
|
```
|
|
|
|
### Uploading Photos
|
|
|
|
```bash
|
|
# Upload a park photo
|
|
curl -X POST "https://api.thrillwiki.com/api/v1/parks/1/photos/" \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
-F "image=@/path/to/photo.jpg" \
|
|
-F "caption=Amazing entrance view" \
|
|
-F "photo_type=ENTRANCE"
|
|
|
|
# Upload a ride photo
|
|
curl -X POST "https://api.thrillwiki.com/api/v1/rides/42/photos/" \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
-F "image=@/path/to/coaster.jpg" \
|
|
-F "caption=First drop" \
|
|
-F "photo_type=GENERAL"
|
|
```
|
|
|
|
---
|
|
|
|
## 🚨 Important Notes
|
|
|
|
1. **Authentication Required**: Most write operations require JWT authentication
|
|
2. **Permissions**: Admin endpoints require staff/superuser privileges
|
|
3. **Rate Limiting**: 60 requests/minute for anonymous, 1000 requests/hour for authenticated users
|
|
4. **File Uploads**: Use `multipart/form-data` for photo uploads (max 10MB)
|
|
5. **Pagination**: Default page size is 20, maximum is 100
|
|
6. **Filtering**: Parks and rides support extensive filtering with range parameters
|
|
7. **Cloudflare Images**: All media files are served through Cloudflare Images CDN
|
|
8. **Email Verification**: New users must verify email before full access
|
|
9. **Token Rotation**: Refresh tokens are rotated on each use for security
|
|
|
|
---
|
|
|
|
This documentation covers all available API endpoints in the ThrillWiki v1 API. For detailed request/response schemas, parameter validation, and interactive testing, visit `/api/docs/` when the development server is running. |