19 KiB
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:
{
"username": "admin",
"password": "secretpassword"
}
Response (200 OK):
{
"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):
{
"detail": "Incorrect username or password"
}
POST /auth/refresh
Refresh access token using refresh token.
Request:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}
Response (200 OK):
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 900
}
GET /auth/me
Get current authenticated user.
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Response (200 OK):
{
"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):
{
"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):
{
"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):
{
"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:
{
"action": "delete", // delete, retry, mark_upgraded
"ids": [1, 2, 3, 4, 5],
"delete_files": false
}
Response (200 OK):
{
"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 platformpage(int): Page numberper_page(int): Items per page
Response (200 OK):
{
"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:
{
"url": "https://instagram.com/evalongoria",
"platform": "instagram",
"source": "evalongoria",
"content_type": "posts",
"priority": 5,
"max_downloads": 15,
"metadata": {
"downloader": "fastdl"
}
}
Response (201 Created):
{
"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:
{
"priority": 1,
"status": "paused"
}
Response (200 OK):
{
"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):
{
"id": 2732,
"status": "pending",
"attempts": 1,
"task_id": "celery-task-uuid-here"
}
POST /queue/clear
Clear completed/failed items from queue.
Request:
{
"status": ["completed", "failed"]
}
Response (200 OK):
{
"deleted": 125
}
GET /queue/stats
Get queue statistics.
Response (200 OK):
{
"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):
{
"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:
{
"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):
{
"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:
{
"schedule": "0 */8 * * *",
"enabled": false
}
Response (200 OK):
{
"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):
{
"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 IDstatus(str): Filter by status (success, failure)limit(int): Number of records (default: 100)
Response (200 OK):
{
"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):
{
"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:
{
"username": "evalongoria",
"content_type": "posts",
"downloader": "fastdl",
"max_downloads": 15,
"days_back": 7,
"priority": 5
}
Response (202 Accepted):
{
"queue_id": 2733,
"task_id": "celery-task-uuid",
"status": "queued",
"message": "Download queued successfully"
}
POST /platforms/tiktok/download
Start TikTok download.
Request:
{
"username": "evalongoria",
"max_downloads": 10,
"priority": 5
}
Response (202 Accepted):
{
"queue_id": 2734,
"task_id": "celery-task-uuid",
"status": "queued"
}
POST /platforms/forum/monitor
Start forum thread monitoring.
Request:
{
"forum_name": "PicturePub",
"thread_url": "https://example.com/thread/123",
"thread_title": "Celebrity Photos",
"monitor_days": 30
}
Response (201 Created):
{
"thread_id": "thread-123",
"status": "active",
"monitor_until": "2025-11-12T15:00:00Z"
}
Settings Endpoints
GET /settings
Get all application settings.
Response (200 OK):
{
"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:
{
"general": {
"concurrent_downloads": 6
},
"platforms": {
"instagram": {
"toolzu": {
"auto_upgrade": false
}
}
}
}
Response (200 OK):
{
"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 messagesdate_from(datetime): From timestampdate_to(datetime): To timestamplimit(int): Number of records (default: 100, max: 1000)
Response (200 OK):
{
"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):
{
"deleted_files": 15,
"deleted_size_bytes": 52428800
}
Statistics Endpoints
GET /stats/overview
Get dashboard overview statistics.
Response (200 OK):
{
"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):
{
"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):
{
"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
{
"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
{
"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
{
"type": "queue_updated",
"timestamp": "2025-10-13T15:45:00.000Z",
"data": {
"action": "added",
"item": {
"id": 2734,
"platform": "tiktok",
"source": "evalongoria",
"status": "pending"
}
}
}
Log Event
{
"type": "log",
"timestamp": "2025-10-13T15:45:23.456Z",
"data": {
"level": "INFO",
"module": "Instagram",
"message": "Started downloading posts from evalongoria"
}
}
System Notification Event
{
"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:
{
"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- Success201 Created- Resource created202 Accepted- Request accepted (async)204 No Content- Success with no response body400 Bad Request- Invalid input401 Unauthorized- Authentication required403 Forbidden- Insufficient permissions404 Not Found- Resource not found409 Conflict- Resource conflict (duplicate)422 Unprocessable Entity- Validation error429 Too Many Requests- Rate limit exceeded500 Internal Server Error- Server error503 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"