# API Specification - Media Downloader Web GUI

## Overview
RESTful API with WebSocket support for real-time updates.

**Base URL:** `http://localhost:8000/api/v1`
**Authentication:** JWT Bearer Token
**Content-Type:** `application/json`

---

## Authentication Endpoints

### POST /auth/login
Login with username and password.

**Request:**
```json
{
  "username": "admin",
  "password": "secretpassword"
}
```

**Response (200 OK):**
```json
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "expires_in": 900,
  "user": {
    "id": 1,
    "username": "admin",
    "email": "admin@example.com",
    "role": "admin"
  }
}
```

**Error Response (401 Unauthorized):**
```json
{
  "detail": "Incorrect username or password"
}
```

---

### POST /auth/refresh
Refresh access token using refresh token.

**Request:**
```json
{
  "refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}
```

**Response (200 OK):**
```json
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "expires_in": 900
}
```

---

### GET /auth/me
Get current authenticated user.

**Headers:**
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```

**Response (200 OK):**
```json
{
  "id": 1,
  "username": "admin",
  "email": "admin@example.com",
  "role": "admin",
  "created_at": "2025-10-01T10:00:00Z",
  "last_login": "2025-10-13T14:30:00Z"
}
```

---

## Download Endpoints

### GET /downloads
List downloads with filtering and pagination.

**Query Parameters:**
- `page` (int): Page number (default: 1)
- `per_page` (int): Items per page (default: 50, max: 200)
- `platform` (str): Filter by platform (instagram, tiktok, forum)
- `source` (str): Filter by source (username/forum name)
- `status` (str): Filter by status (completed, failed)
- `date_from` (date): Filter from date (YYYY-MM-DD)
- `date_to` (date): Filter to date (YYYY-MM-DD)
- `search` (str): Search in URLs and filenames

**Example Request:**
```
GET /downloads?platform=instagram&source=evalongoria&page=1&per_page=20
```

**Response (200 OK):**
```json
{
  "items": [
    {
      "id": 1885,
      "url": "https://instagram.com/p/ABC123/",
      "url_hash": "a1b2c3d4e5f6...",
      "platform": "instagram",
      "source": "evalongoria",
      "content_type": "post",
      "filename": "evalongoria_20251012_141523_123456789.jpg",
      "file_path": "/opt/media-downloader/downloads/fastdl/evalongoria/evalongoria_20251012_141523_123456789.jpg",
      "file_size": 2457600,
      "file_hash": "sha256:abc123...",
      "post_date": "2025-10-12T14:15:23Z",
      "download_date": "2025-10-12T14:20:45Z",
      "status": "completed",
      "attempts": 1,
      "metadata": {
        "media_id": "123456789",
        "resolution": "640x640",
        "upgraded": false
      }
    }
  ],
  "total": 1885,
  "page": 1,
  "per_page": 20,
  "total_pages": 95
}
```

---

### GET /downloads/{id}
Get single download by ID.

**Response (200 OK):**
```json
{
  "id": 1885,
  "url": "https://instagram.com/p/ABC123/",
  "platform": "instagram",
  "source": "evalongoria",
  "content_type": "post",
  "filename": "evalongoria_20251012_141523_123456789.jpg",
  "file_path": "/opt/media-downloader/downloads/fastdl/evalongoria/evalongoria_20251012_141523_123456789.jpg",
  "file_size": 2457600,
  "file_hash": "sha256:abc123...",
  "post_date": "2025-10-12T14:15:23Z",
  "download_date": "2025-10-12T14:20:45Z",
  "status": "completed",
  "attempts": 1,
  "metadata": {
    "media_id": "123456789",
    "resolution": "640x640",
    "upgraded": false
  },
  "thumbnail_url": "/api/v1/downloads/1885/thumbnail"
}
```

---

### DELETE /downloads/{id}
Delete download record (optionally delete file).

**Query Parameters:**
- `delete_file` (bool): Also delete the physical file (default: false)

**Response (204 No Content)**

---

### GET /downloads/stats
Get download statistics.

**Query Parameters:**
- `period` (str): Time period (today, week, month, year, all)
- `group_by` (str): Group by field (platform, source, content_type)

**Response (200 OK):**
```json
{
  "total_downloads": 1885,
  "completed": 1870,
  "failed": 15,
  "success_rate": 99.2,
  "total_size_bytes": 45678901234,
  "by_platform": {
    "instagram": 333,
    "fastdl": 18,
    "tiktok": 12,
    "forum": 1522
  },
  "by_source": {
    "evalongoria": 186,
    "PicturePub": 1332,
    "HQCelebCorner": 190
  },
  "timeline": [
    {"date": "2025-10-06", "count": 15},
    {"date": "2025-10-07", "count": 23},
    {"date": "2025-10-08", "count": 31}
  ]
}
```

---

### POST /downloads/bulk
Bulk operations on downloads.

**Request:**
```json
{
  "action": "delete",  // delete, retry, mark_upgraded
  "ids": [1, 2, 3, 4, 5],
  "delete_files": false
}
```

**Response (200 OK):**
```json
{
  "success": 5,
  "failed": 0,
  "errors": []
}
```

---

## Queue Endpoints

### GET /queue
Get download queue items.

**Query Parameters:**
- `status` (str): Filter by status (pending, downloading, completed, failed)
- `platform` (str): Filter by platform
- `page` (int): Page number
- `per_page` (int): Items per page

**Response (200 OK):**
```json
{
  "items": [
    {
      "id": 2731,
      "url": "https://instagram.com/evalongoria",
      "platform": "forum",
      "source": "PicturePub",
      "referer": null,
      "save_path": "/opt/media-downloader/downloads/forum/PicturePub",
      "priority": 5,
      "status": "pending",
      "attempts": 0,
      "max_attempts": 3,
      "created_date": "2025-10-13T10:30:00Z",
      "started_at": null,
      "download_date": null,
      "progress": 0,
      "estimated_completion": null,
      "assigned_worker": null,
      "error_message": null,
      "metadata": {
        "thread_id": "thread-12345",
        "content_type": "images"
      }
    }
  ],
  "total": 2731,
  "pending": 2731,
  "downloading": 0,
  "completed": 0,
  "failed": 0
}
```

---

### POST /queue
Add item to download queue.

**Request:**
```json
{
  "url": "https://instagram.com/evalongoria",
  "platform": "instagram",
  "source": "evalongoria",
  "content_type": "posts",
  "priority": 5,
  "max_downloads": 15,
  "metadata": {
    "downloader": "fastdl"
  }
}
```

**Response (201 Created):**
```json
{
  "id": 2732,
  "url": "https://instagram.com/evalongoria",
  "platform": "instagram",
  "source": "evalongoria",
  "status": "pending",
  "created_date": "2025-10-13T15:45:00Z",
  "task_id": "celery-task-uuid-here"
}
```

---

### PATCH /queue/{id}
Update queue item.

**Request:**
```json
{
  "priority": 1,
  "status": "paused"
}
```

**Response (200 OK):**
```json
{
  "id": 2732,
  "status": "paused",
  "priority": 1
}
```

---

### DELETE /queue/{id}
Remove item from queue.

**Response (204 No Content)**

---

### POST /queue/{id}/retry
Retry failed download.

**Response (200 OK):**
```json
{
  "id": 2732,
  "status": "pending",
  "attempts": 1,
  "task_id": "celery-task-uuid-here"
}
```

---

### POST /queue/clear
Clear completed/failed items from queue.

**Request:**
```json
{
  "status": ["completed", "failed"]
}
```

**Response (200 OK):**
```json
{
  "deleted": 125
}
```

---

### GET /queue/stats
Get queue statistics.

**Response (200 OK):**
```json
{
  "total": 2731,
  "pending": 2700,
  "downloading": 5,
  "completed": 20,
  "failed": 6,
  "avg_wait_time_seconds": 120,
  "estimated_completion": "2025-10-13T18:30:00Z",
  "active_workers": 4
}
```

---

## Scheduler Endpoints

### GET /scheduler/jobs
List all scheduled jobs.

**Response (200 OK):**
```json
{
  "jobs": [
    {
      "id": "instagram-evalongoria-posts",
      "name": "Eva Longoria Instagram Posts",
      "platform": "instagram",
      "source": "evalongoria",
      "content_type": "posts",
      "schedule": "0 */4 * * *",  // Every 4 hours
      "schedule_human": "Every 4 hours",
      "enabled": true,
      "last_run": "2025-10-13T12:00:00Z",
      "last_run_status": "success",
      "last_run_items": 8,
      "next_run": "2025-10-13T16:00:00Z",
      "total_runs": 245,
      "success_count": 240,
      "failure_count": 5,
      "config": {
        "max_downloads": 15,
        "downloader": "fastdl"
      }
    }
  ]
}
```

---

### POST /scheduler/jobs
Create new scheduled job.

**Request:**
```json
{
  "name": "Eva Longoria Stories",
  "platform": "instagram",
  "source": "evalongoria",
  "content_type": "stories",
  "schedule": "0 */6 * * *",
  "enabled": true,
  "config": {
    "max_downloads": 50,
    "downloader": "fastdl"
  }
}
```

**Response (201 Created):**
```json
{
  "id": "instagram-evalongoria-stories",
  "name": "Eva Longoria Stories",
  "next_run": "2025-10-13T18:00:00Z",
  "enabled": true
}
```

---

### PATCH /scheduler/jobs/{id}
Update scheduled job.

**Request:**
```json
{
  "schedule": "0 */8 * * *",
  "enabled": false
}
```

**Response (200 OK):**
```json
{
  "id": "instagram-evalongoria-stories",
  "schedule": "0 */8 * * *",
  "enabled": false,
  "next_run": null
}
```

---

### DELETE /scheduler/jobs/{id}
Delete scheduled job.

**Response (204 No Content)**

---

### POST /scheduler/jobs/{id}/run
Manually trigger job execution.

**Response (202 Accepted):**
```json
{
  "task_id": "celery-task-uuid",
  "status": "queued",
  "message": "Job execution queued"
}
```

---

### GET /scheduler/history
Get job execution history.

**Query Parameters:**
- `job_id` (str): Filter by job ID
- `status` (str): Filter by status (success, failure)
- `limit` (int): Number of records (default: 100)

**Response (200 OK):**
```json
{
  "history": [
    {
      "id": 1234,
      "job_id": "instagram-evalongoria-posts",
      "started_at": "2025-10-13T12:00:00Z",
      "completed_at": "2025-10-13T12:03:45Z",
      "duration_seconds": 225,
      "status": "success",
      "items_downloaded": 8,
      "error_message": null
    }
  ]
}
```

---

## Platform Endpoints

### GET /platforms
List all supported platforms.

**Response (200 OK):**
```json
{
  "platforms": [
    {
      "name": "instagram",
      "display_name": "Instagram",
      "enabled": true,
      "downloaders": [
        {
          "name": "fastdl",
          "display_name": "FastDL (640x640)",
          "enabled": true
        },
        {
          "name": "toolzu",
          "display_name": "Toolzu (1920x1440)",
          "enabled": true
        }
      ],
      "content_types": ["posts", "stories", "reels"],
      "features": ["quality_upgrade", "date_filtering", "limit_downloads"],
      "status": "operational",
      "last_successful_download": "2025-10-13T14:30:00Z"
    },
    {
      "name": "tiktok",
      "display_name": "TikTok",
      "enabled": true,
      "content_types": ["videos"],
      "status": "operational"
    }
  ]
}
```

---

### POST /platforms/instagram/download
Start Instagram download.

**Request:**
```json
{
  "username": "evalongoria",
  "content_type": "posts",
  "downloader": "fastdl",
  "max_downloads": 15,
  "days_back": 7,
  "priority": 5
}
```

**Response (202 Accepted):**
```json
{
  "queue_id": 2733,
  "task_id": "celery-task-uuid",
  "status": "queued",
  "message": "Download queued successfully"
}
```

---

### POST /platforms/tiktok/download
Start TikTok download.

**Request:**
```json
{
  "username": "evalongoria",
  "max_downloads": 10,
  "priority": 5
}
```

**Response (202 Accepted):**
```json
{
  "queue_id": 2734,
  "task_id": "celery-task-uuid",
  "status": "queued"
}
```

---

### POST /platforms/forum/monitor
Start forum thread monitoring.

**Request:**
```json
{
  "forum_name": "PicturePub",
  "thread_url": "https://example.com/thread/123",
  "thread_title": "Celebrity Photos",
  "monitor_days": 30
}
```

**Response (201 Created):**
```json
{
  "thread_id": "thread-123",
  "status": "active",
  "monitor_until": "2025-11-12T15:00:00Z"
}
```

---

## Settings Endpoints

### GET /settings
Get all application settings.

**Response (200 OK):**
```json
{
  "general": {
    "download_directory": "/opt/media-downloader/downloads",
    "concurrent_downloads": 4,
    "retry_attempts": 3,
    "default_priority": 5,
    "storage_limit_gb": 500,
    "auto_cleanup_days": 180
  },
  "platforms": {
    "instagram": {
      "fastdl": {
        "enabled": true,
        "rate_limit_per_hour": 100
      },
      "toolzu": {
        "enabled": true,
        "auto_upgrade": true,
        "captcha_api_key": "***"
      }
    },
    "tiktok": {
      "enabled": true,
      "quality": "hd"
    }
  },
  "notifications": {
    "email": {
      "enabled": false,
      "smtp_host": "",
      "smtp_port": 587
    },
    "browser": {
      "enabled": true
    }
  }
}
```

---

### PATCH /settings
Update settings.

**Request:**
```json
{
  "general": {
    "concurrent_downloads": 6
  },
  "platforms": {
    "instagram": {
      "toolzu": {
        "auto_upgrade": false
      }
    }
  }
}
```

**Response (200 OK):**
```json
{
  "message": "Settings updated successfully",
  "updated_fields": 2
}
```

---

## Logs Endpoints

### GET /logs
Get application logs.

**Query Parameters:**
- `level` (str): Filter by level (DEBUG, INFO, WARNING, ERROR)
- `module` (str): Filter by module (Instagram, TikTok, Scheduler, etc.)
- `search` (str): Search in log messages
- `date_from` (datetime): From timestamp
- `date_to` (datetime): To timestamp
- `limit` (int): Number of records (default: 100, max: 1000)

**Response (200 OK):**
```json
{
  "logs": [
    {
      "id": 12345,
      "timestamp": "2025-10-13T15:45:23.456Z",
      "level": "INFO",
      "module": "Instagram",
      "message": "Downloaded 8 posts from evalongoria",
      "metadata": {
        "username": "evalongoria",
        "count": 8,
        "duration_seconds": 45
      }
    }
  ],
  "total": 12345,
  "filtered": 100
}
```

---

### GET /logs/download
Download log file.

**Query Parameters:**
- `date` (date): Log file date (YYYY-MM-DD)
- `format` (str): Format (json, text)

**Response (200 OK):**
```
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="media_downloader_20251013.log"

[Log file content]
```

---

### DELETE /logs
Clear old logs.

**Query Parameters:**
- `older_than_days` (int): Delete logs older than N days

**Response (200 OK):**
```json
{
  "deleted_files": 15,
  "deleted_size_bytes": 52428800
}
```

---

## Statistics Endpoints

### GET /stats/overview
Get dashboard overview statistics.

**Response (200 OK):**
```json
{
  "downloads": {
    "today": 45,
    "week": 312,
    "month": 1205,
    "total": 1885
  },
  "queue": {
    "pending": 2731,
    "downloading": 5,
    "failed": 6
  },
  "success_rate": {
    "today": 97.8,
    "week": 98.5,
    "month": 99.2
  },
  "storage": {
    "used_bytes": 45678901234,
    "used_human": "42.5 GB",
    "limit_bytes": 536870912000,
    "limit_human": "500 GB",
    "percent": 8.5
  },
  "platforms": {
    "instagram": {
      "status": "operational",
      "downloads_today": 35
    },
    "tiktok": {
      "status": "operational",
      "downloads_today": 2
    },
    "forum": {
      "status": "operational",
      "downloads_today": 8
    }
  },
  "next_scheduled_task": {
    "job_id": "instagram-evalongoria-posts",
    "job_name": "Eva Longoria Instagram Posts",
    "scheduled_time": "2025-10-13T16:00:00Z",
    "in_seconds": 873
  }
}
```

---

### GET /stats/timeline
Get downloads over time.

**Query Parameters:**
- `period` (str): Period (day, week, month, year)
- `group_by` (str): Group by (hour, day, week, month)

**Response (200 OK):**
```json
{
  "timeline": [
    {
      "timestamp": "2025-10-06T00:00:00Z",
      "downloads": 45,
      "success": 44,
      "failed": 1
    },
    {
      "timestamp": "2025-10-07T00:00:00Z",
      "downloads": 52,
      "success": 52,
      "failed": 0
    }
  ]
}
```

---

### GET /stats/platforms
Get breakdown by platform.

**Response (200 OK):**
```json
{
  "platforms": [
    {
      "platform": "instagram",
      "downloads": 351,
      "success": 348,
      "failed": 3,
      "success_rate": 99.1,
      "total_size_bytes": 15678901234
    },
    {
      "platform": "forum",
      "downloads": 1522,
      "success": 1520,
      "failed": 2,
      "success_rate": 99.9,
      "total_size_bytes": 28678901234
    }
  ]
}
```

---

## WebSocket Events

### Connection
```
WS ws://localhost:8000/ws/downloads?token=JWT_TOKEN
```

### Download Progress Event
```json
{
  "type": "download_progress",
  "timestamp": "2025-10-13T15:45:23.456Z",
  "data": {
    "queue_id": 2733,
    "url": "https://instagram.com/evalongoria",
    "platform": "instagram",
    "source": "evalongoria",
    "status": "downloading",
    "progress": 65,
    "items_downloaded": 13,
    "items_total": 20,
    "current_item": "evalongoria_20251012_141523_123456789.jpg",
    "speed_mbps": 2.5,
    "eta_seconds": 45
  }
}
```

### Download Complete Event
```json
{
  "type": "download_completed",
  "timestamp": "2025-10-13T15:48:15.123Z",
  "data": {
    "queue_id": 2733,
    "platform": "instagram",
    "source": "evalongoria",
    "items_downloaded": 20,
    "duration_seconds": 172,
    "status": "completed"
  }
}
```

### Queue Update Event
```json
{
  "type": "queue_updated",
  "timestamp": "2025-10-13T15:45:00.000Z",
  "data": {
    "action": "added",
    "item": {
      "id": 2734,
      "platform": "tiktok",
      "source": "evalongoria",
      "status": "pending"
    }
  }
}
```

### Log Event
```json
{
  "type": "log",
  "timestamp": "2025-10-13T15:45:23.456Z",
  "data": {
    "level": "INFO",
    "module": "Instagram",
    "message": "Started downloading posts from evalongoria"
  }
}
```

### System Notification Event
```json
{
  "type": "notification",
  "timestamp": "2025-10-13T15:48:15.123Z",
  "data": {
    "level": "success",
    "title": "Download Complete",
    "message": "Downloaded 20 posts from evalongoria",
    "action": {
      "label": "View Downloads",
      "link": "/history?source=evalongoria"
    },
    "auto_dismiss_seconds": 5
  }
}
```

---

## Error Responses

All errors follow this format:

```json
{
  "detail": "Error message",
  "error_code": "SPECIFIC_ERROR_CODE",
  "timestamp": "2025-10-13T15:45:23.456Z",
  "request_id": "uuid-here"
}
```

### Common HTTP Status Codes
- `200 OK` - Success
- `201 Created` - Resource created
- `202 Accepted` - Request accepted (async)
- `204 No Content` - Success with no response body
- `400 Bad Request` - Invalid input
- `401 Unauthorized` - Authentication required
- `403 Forbidden` - Insufficient permissions
- `404 Not Found` - Resource not found
- `409 Conflict` - Resource conflict (duplicate)
- `422 Unprocessable Entity` - Validation error
- `429 Too Many Requests` - Rate limit exceeded
- `500 Internal Server Error` - Server error
- `503 Service Unavailable` - Service temporarily unavailable

---

## Rate Limiting

**Headers:**
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1697203200
```

**Limits:**
- Public endpoints: 100 requests/hour
- Authenticated endpoints: 1000 requests/hour
- WebSocket connections: 10 per user

---

## Pagination

All list endpoints support pagination:

**Request:**
```
GET /downloads?page=2&per_page=50
```

**Response Headers:**
```
X-Total-Count: 1885
X-Page: 2
X-Per-Page: 50
X-Total-Pages: 38
Link: </api/v1/downloads?page=1>; rel="first", </api/v1/downloads?page=3>; rel="next"
```
