# 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 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](./architecture/adr-007-logging-standardization.md) for details.

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