Files
thrillwiki_django_no_react/docs/THRILLWIKI_API_DOCUMENTATION.md
pacnpal ca770d76ff Enhance documentation and management commands for ThrillWiki
- Updated backend README.md to include detailed management commands for configuration, database operations, cache management, data management, user authentication, content/media handling, trending/discovery, testing/development, and security/auditing.
- Added a new MANAGEMENT_COMMANDS.md file for comprehensive command reference.
- Included logging standardization details in architecture documentation (ADR-007).
- Improved production checklist with configuration validation and cache verification steps.
- Expanded API documentation to include error logging details.
- Created a documentation review checklist to ensure completeness and accuracy.
2025-12-23 21:28:14 -05:00

42 KiB

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:

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

{
  "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

{
  "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:

{
  "username": "johndoe",
  "password": "securepassword123"
}

curl Example:

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):

{
  "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):

{
  "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:

{
  "username": "newuser",
  "email": "newuser@example.com",
  "password1": "ComplexPass123!",
  "password2": "ComplexPass123!"
}

curl Example:

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):

{
  "success": true,
  "message": "Verification email sent. Please check your inbox.",
  "user": {
    "id": 43,
    "username": "newuser",
    "email": "newuser@example.com"
  }
}

Error Response (400 Bad Request):

{
  "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):

{
  "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}

curl Example:

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):

{
  "message": "Successfully logged out."
}

GET /auth/user/ - Get Current User

Retrieve the authenticated user's information.

Authentication: Required

curl Example:

curl -X GET https://api.thrillwiki.com/api/v1/auth/user/ \
  -H "Authorization: Bearer <access_token>"

Success Response (200 OK):

{
  "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:

curl -X POST https://api.thrillwiki.com/api/v1/auth/status/ \
  -H "Authorization: Bearer <access_token>"

Authenticated Response (200 OK):

{
  "authenticated": true,
  "user": {
    "id": 42,
    "username": "johndoe"
  }
}

Unauthenticated Response (200 OK):

{
  "authenticated": false
}

POST /auth/password/reset/ - Request Password Reset

Request a password reset email.

Request Body:

{
  "email": "johndoe@example.com"
}

curl Example:

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):

{
  "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:

{
  "old_password": "currentpassword",
  "new_password1": "NewComplexPass123!",
  "new_password2": "NewComplexPass123!"
}

curl Example:

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):

{
  "message": "Password changed successfully."
}

POST /auth/token/refresh/ - Refresh Access Token

Obtain a new access token using a refresh token.

Request Body:

{
  "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}

curl Example:

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):

{
  "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:

curl -X GET https://api.thrillwiki.com/api/v1/auth/social/providers/

Success Response (200 OK):

[
  {
    "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:

# 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):

{
  "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:

curl -X GET https://api.thrillwiki.com/api/v1/parks/cedar-point/

Success Response (200 OK):

{
  "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):

{
  "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:

{
  "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:

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):

{
  "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:

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):

{
  "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:

{
  "photo_ids": [523, 524, 525],
  "approve": true
}

curl Example:

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):

{
  "success": true,
  "message": "3 photos approved successfully.",
  "processed": 3
}

Error Response (403 Forbidden):

{
  "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:

curl -X GET https://api.thrillwiki.com/api/v1/parks/filter-metadata/

Success Response (200 OK):

{
  "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:

# 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):

{
  "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:

curl -X GET https://api.thrillwiki.com/api/v1/rides/steel-vengeance/

Success Response (200 OK):

{
  "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:

{
  "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:

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):

{
  "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/)

  • 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
  • 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

headers: {
  'Authorization': 'Bearer <access_token>',
  'Content-Type': 'application/json'
}

Pagination Response

{
  "count": 100,
  "next": "https://api.thrillwiki.com/api/v1/endpoint/?page=2",
  "previous": null,
  "results": [...]
}

Success Response Format

{
  "success": true,
  "message": "Operation completed successfully",
  "data": {...}
}

Error Response Reference

All error responses follow a consistent format with appropriate HTTP status codes.

Error Logging

All API errors are logged with full context for debugging:

  • Request details (method, path, user)
  • Error type and message
  • Stack trace (for 500 errors)
  • Request payload (sanitized)

Logs are sent to Sentry in production for monitoring.

See ADR-007: Logging Standardization for details.

Error Response Structure

{
  "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)

{
  "error": "Authentication credentials were not provided",
  "error_code": "AUTHENTICATION_REQUIRED"
}
{
  "error": "Token is invalid or expired",
  "error_code": "INVALID_TOKEN",
  "details": {
    "token_type": "access",
    "message": "Token has expired"
  }
}

Authorization Errors (403)

{
  "error": "Permission denied",
  "error_code": "FORBIDDEN",
  "details": {
    "message": "You do not have permission to perform this action.",
    "required_permission": "is_staff"
  }
}

Validation Errors (400)

{
  "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)

{
  "error": "Park not found",
  "error_code": "NOT_FOUND",
  "details": {
    "resource": "Park",
    "identifier": "nonexistent-park-slug"
  }
}

Rate Limit Errors (429)

{
  "error": "Request was throttled",
  "error_code": "RATE_LIMIT_EXCEEDED",
  "detail": "Expected available in 45 seconds.",
  "retry_after": 45
}

Conflict Errors (409)

{
  "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

# 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

# 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

# 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

# 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.