Media Downloader API
Complete reference for integrating with the Media Downloader API — version 3.1
Overview
The Media Downloader API provides programmatic access to download media from Instagram, TikTok, YouTube, Facebook, Twitter, Pinterest, and other platforms. All download operations are asynchronous.
- All endpoints are under
/api/v1/ - Requests and responses use
application/json - Downloads are async: submit → get
task_id→ poll untilcompleted - Files can be fetched directly or via a 307 redirect to Wasabi/S3 cloud storage
- Interactive Swagger UI: /docs
Quick Start
Download a video in three steps:
# Step 1: Submit curl -X POST https://medialoader.69media.pro/api/v1/download \ -H "Content-Type: application/json" \ -H "X-API-Key: YOUR_API_KEY" \ -d '{"url":"https://www.instagram.com/p/ABC123/"}' # Step 2: Poll (replace TASK_ID with the id from step 1) curl https://medialoader.69media.pro/api/v1/tasks/TASK_ID \ -H "X-API-Key: YOUR_API_KEY" # Step 3: Download file (replace PATH with files[0] value from step 2) curl -OJ -L https://medialoader.69media.pro/api/v1/files/PATH \ -H "X-API-Key: YOUR_API_KEY"
import requests, time BASE = "https://medialoader.69media.pro/api/v1" HDRS = {"X-API-Key": "YOUR_API_KEY"} # Step 1: Submit r = requests.post(f"{BASE}/download", json={"url": "https://www.instagram.com/p/ABC123/"}, headers=HDRS) task_id = r.json()["id"] # Step 2: Poll until done while True: task = requests.get(f"{BASE}/tasks/{task_id}", headers=HDRS).json() if task["status"] in ("completed", "error"): break time.sleep(2) # Step 3: Download files (task["files"] is a list of relative path strings) for f in task.get("files", []): data = requests.get(f"{BASE}/files/{f}", headers=HDRS) filename = f.split("/")[-1] with open(filename, "wb") as fp: fp.write(data.content)
const BASE = "https://medialoader.69media.pro/api/v1"; const HDRS = { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" }; // Step 1: Submit const { id } = await fetch(`${BASE}/download`, { method: "POST", headers: HDRS, body: JSON.stringify({ url: "https://www.instagram.com/p/ABC123/" }) }).then(r => r.json()); // Step 2: Poll let task; do { await new Promise(r => setTimeout(r, 2000)); task = await fetch(`${BASE}/tasks/${id}`, { headers: HDRS }).then(r => r.json()); } while (!["completed", "error"].includes(task.status)); // Step 3: files is an array of relative path strings console.log(task.files?.map(f => `${BASE}/files/${encodeURIComponent(f)}`));
Authentication
When API key authentication is enabled, every request to /api/* must include the key. Admin routes always require a separate admin token.
X-API-Key header entirely.API Key Header (recommended)
GET /api/v1/tasks HTTP/1.1 X-API-Key: YOUR_API_KEY Content-Type: application/json
Query Parameter (legacy)
Supported for backward compatibility. Avoid — keys are visible in logs and browser history.
GET /api/v1/tasks?api_key=YOUR_API_KEY
Admin Token
Admin endpoints (/api/v1/admin/*) require X-Admin-Token obtained from POST /api/v1/admin/login.
GET /api/v1/admin/me HTTP/1.1 X-Admin-Token: <token from POST /api/v1/admin/login>
Base URL
| Environment | Base URL |
|---|---|
| Production | https://medialoader.69media.pro |
| Local dev | http://localhost:8000 |
Error Codes
| HTTP | Meaning | Common cause |
|---|---|---|
| 200 | OK | Success |
| 202 | Accepted | Download task queued |
| 400 | Bad Request | Invalid parameters or URL |
| 401 | Unauthorized | Missing or wrong API key / admin token |
| 403 | Forbidden | Insufficient admin role |
| 404 | Not Found | Task, file, or session doesn't exist |
| 409 | Conflict | Resource already exists |
| 422 | Validation Error | Request body schema error |
| 429 | Too Many Requests | Rate limit exceeded (see X-RateLimit-Reset) |
| 500 | Server Error | Unexpected server failure |
All error responses: {"detail": "Human-readable message"}
Rate Limits
Default: 240 requests per minute per IP. When exceeded the server returns 429 with headers X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and Retry-After.
Download Endpoints
Submits a download task and returns immediately with a task object (HTTP 202). The actual download runs in the background — poll GET /tasks/{id} for progress.
Request body
| Field | Type | Description |
|---|---|---|
| urlrequired | string | Full media URL (Instagram, TikTok, YouTube, Facebook, Twitter, Pinterest, etc.) |
| qualityoptional | string | max (default), high, medium, low |
| download_alloptional | boolean | Fetch all items from a carousel/playlist (default: false) |
| max_itemsoptional | integer | Limit items for profiles/playlists (1–10 000) |
| proxyoptional | string | Outbound proxy URL for this download |
Response — 202 Accepted (TaskStatusInfo)
| Field | Type | Description |
|---|---|---|
| id | string | Task UUID — use to poll status |
| status | string | pending | downloading | uploading | completed | error |
| progress | float | 0.0 – 100.0 |
| platform | string | Detected platform (instagram, tiktok, youtube, …) |
| files | array<string> | Relative file paths (populated after completion) |
| error | string|null | Error message when status is error |
| wasabi_urls | object | Map of path → presigned URL for cloud-stored files |
| source_url | string | Original media URL on the source platform |
| profile_url | string | Author profile/channel URL |
curl -X POST https://medialoader.69media.pro/api/v1/download \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://www.tiktok.com/@user/video/7123456789", "quality": "max" }'
requests.post(
"https://medialoader.69media.pro/api/v1/download",
json={"url": "https://www.tiktok.com/@user/video/7123456789", "quality": "max"},
headers={"X-API-Key": "YOUR_API_KEY"}
)
{
"id": "3f1a2b4c-8d9e-4f0a-b1c2-d3e4f5a6b7c8",
"url": "https://www.tiktok.com/@user/video/7123456789",
"status": "pending",
"progress": 0.0,
"platform": "tiktok",
"files": [],
"error": null,
"created_at": 1714000000.0,
"elapsed_seconds": 0.0,
"total_items": 0,
"downloaded_items": 0,
"wasabi_urls": {},
"source_url": "",
"profile_url": ""
}
Submit up to 50 URLs in a single call. Duplicates are deduplicated. Each URL becomes an independent task. Returns {"tasks": [...]}.
| Field | Type | Description |
|---|---|---|
| urlsrequired | array<string> | 1–50 URLs |
| qualityoptional | string | Same as single download |
| download_alloptional | boolean | Apply to all URLs |
| max_itemsoptional | integer | Applied per URL |
| proxyoptional | string | Shared proxy for all URLs |
curl -X POST https://medialoader.69media.pro/api/v1/batch-download \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "urls": [ "https://www.instagram.com/p/ABC123/", "https://www.tiktok.com/@user/video/7123456789" ], "quality": "max" }'
Returns the current state of a task. Poll every 2–5 seconds until status is completed or error.
status == "completed", the files field is an array of relative path strings (e.g. "tiktok/user/video.mp4"). Use these paths with GET /api/v1/files/{path}.curl https://medialoader.69media.pro/api/v1/tasks/3f1a2b4c-8d9e-4f0a-b1c2-d3e4f5a6b7c8 \
-H "X-API-Key: YOUR_API_KEY"
{
"id": "3f1a2b4c-8d9e-4f0a-b1c2-d3e4f5a6b7c8",
"status": "completed",
"progress": 100.0,
"elapsed_seconds": 4.2,
"files": ["tiktok/user/video.mp4"],
"total_items": 1,
"downloaded_items": 1,
"source_url": "https://www.tiktok.com/@user/video/7123456789",
"profile_url": "https://www.tiktok.com/@user",
"wasabi_urls": {}
}
| Query param | Type | Description |
|---|---|---|
| statusoptional | string | Filter: pending, downloading, uploading, completed, error |
| limitoptional | integer | Max results (1–500, default 100) |
| offsetoptional | integer | Pagination offset (default 0) |
curl "https://medialoader.69media.pro/api/v1/tasks?status=completed&limit=20" \ -H "X-API-Key: YOUR_API_KEY"
Attempts to cancel a pending or downloading task. Returns {"id": "...", "cancelled": true} if successful, or {"cancelled": false} if the task was already finished.
curl -X DELETE https://medialoader.69media.pro/api/v1/tasks/TASK_ID \
-H "X-API-Key: YOUR_API_KEY"
File Endpoints
Returns all files in the download directory with optional filtering and sorting. Response: {"total": N, "files": [...]}.
| Query param | Type | Description |
|---|---|---|
| sortoptional | string | date (default), name, size |
| media_typeoptional | string | Filter: video | image | audio | other |
| platformoptional | string | Filter by platform folder (e.g. tiktok) |
| profileoptional | string | Filter by source profile/channel name |
Each file object includes: name, size_bytes, size_human, modified, media_type, source_platform, source_profile, wasabi (bool), download_url, thumbnail_url, source_url, profile_url.
curl "https://medialoader.69media.pro/api/v1/files" \ -H "X-API-Key: YOUR_API_KEY"
{
"total": 142,
"files": [
{
"name": "Instagram/user123/video_abc.mp4",
"size_bytes": 14532096,
"size_human": "13.9 MB",
"modified": 1747123456.0,
"media_type": "video",
"source_platform": "Instagram",
"source_profile": "user123",
"wasabi": false,
"download_url": "/api/v1/files/Instagram/user123/video_abc.mp4",
"thumbnail_url": "/api/v1/thumbs/Instagram/user123/video_abc.mp4",
"source_url": "https://www.instagram.com/reel/Cxyz/",
"profile_url": "https://www.instagram.com/user123/"
}
]
}
# Only videos from Instagram, sorted by size curl "https://medialoader.69media.pro/api/v1/files?media_type=video&platform=Instagram&sort=size" \ -H "X-API-Key: YOUR_API_KEY" # Images from a specific profile curl "https://medialoader.69media.pro/api/v1/files?media_type=image&profile=user123" \ -H "X-API-Key: YOUR_API_KEY"
Returns unique profile/channel names extracted from download paths, with file counts and total bytes.
| Query param | Type | Description |
|---|---|---|
| platformoptional | string | Filter by platform |
curl "https://medialoader.69media.pro/api/v1/profiles?platform=instagram" \ -H "X-API-Key: YOUR_API_KEY"
Returns the file as a binary response, or a 307 Temporary Redirect to Wasabi/S3 cloud storage if the file is stored remotely. Media files are served inline; other types as attachments.
# Download and save with original filename (-L follows 307 redirect) curl -OJ -L https://medialoader.69media.pro/api/v1/files/tiktok%2Fuser%2Fvideo.mp4 \ -H "X-API-Key: YOUR_API_KEY"
Deletes the specified file locally and removes it from the Wasabi manifest. Returns {"deleted": "path/to/file.mp4"}.
curl -X DELETE https://medialoader.69media.pro/api/v1/files/tiktok%2Fuser%2Fvideo.mp4 \
-H "X-API-Key: YOUR_API_KEY"
?confirm=true.curl -X DELETE "https://medialoader.69media.pro/api/v1/files?confirm=true" \ -H "X-API-Key: YOUR_API_KEY"
Builds a ZIP from the supplied relative file paths and streams it back. Returns application/zip.
| Field | Type | Description |
|---|---|---|
| filesrequired | array<string> | Relative paths of files to include in the archive |
curl -X POST https://medialoader.69media.pro/api/v1/files/archive \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"files":["tiktok/user/video1.mp4","instagram/user/photo.jpg"]}' \ -o archive.zip
Returns a cached JPEG thumbnail for a video file. Generated on first request via ffmpeg. Supports Wasabi-stored files. Response: image/jpeg, cached for 24 hours.
curl https://medialoader.69media.pro/api/v1/thumbs/tiktok%2Fuser%2Fvideo.mp4 \
-H "X-API-Key: YOUR_API_KEY" -o thumb.jpg
Gallery Endpoints
Saves a list of downloaded file paths under a unique token. The resulting /gallery/{token} page is publicly accessible without authentication and renders all media inline.
| Body field | Type | Description |
|---|---|---|
| filesrequired | array<string> | Relative file paths from GET /api/v1/files (1–200 items) |
| titleoptional | string | Optional display title for the gallery (max 120 chars) |
curl -X POST https://medialoader.69media.pro/api/v1/gallery \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"files":["tiktok/user/video.mp4","instagram/post/photo.jpg"],"title":"My Gallery"}'
resp = requests.post(f"{BASE}/gallery", headers=HDRS, json={ "files": ["tiktok/user/video.mp4", "instagram/post/photo.jpg"], "title": "My Gallery" }) data = resp.json() # data["url"] → public URL, data["token"] → unique token print(data["url"])
Response: {"token": "abc123...", "url": "/gallery/abc123..."}
Returns the file list and title for a gallery token. Publicly accessible — no API key required. To view the rendered gallery page use /gallery/{token} (HTML).
curl https://medialoader.69media.pro/api/v1/gallery/YOUR_TOKEN
Response: {"token": "...", "title": "...", "files": [...], "created_at": "..."}
History Endpoints
Returns past download attempts (success and error) in reverse-chronological order.
| Query param | Type | Description |
|---|---|---|
| limitoptional | integer | Max results (1–500, default 50) |
| offsetoptional | integer | Pagination offset (default 0) |
| platformoptional | string | Filter by platform |
| statusoptional | string | Filter: success | error |
curl "https://medialoader.69media.pro/api/v1/history?limit=20&status=success" \ -H "X-API-Key: YOUR_API_KEY"
Deletes all history entries. Returns {"status": "ok", "cleared": N}.
curl -X DELETE https://medialoader.69media.pro/api/v1/history \
-H "X-API-Key: YOUR_API_KEY"
System Endpoints
Returns server status, version, uptime, storage stats, and availability of optional components.
curl https://medialoader.69media.pro/api/v1/health \
-H "X-API-Key: YOUR_API_KEY"
{
"status": "ok",
"version": "3.1.0",
"uptime_seconds": 86400.0,
"download_dir": "/app/downloads",
"total_files": 42,
"total_size_human": "1.2 GB",
"active_tasks": 2,
"proxy_pool": {
"total_parsed": 334492,
"verified_pool_size": 98,
"https_capable": 14,
"socks5_count": 10,
"socks4_count": 84,
"blacklisted": 0,
"avg_speed_ms": 1329,
"fastest_ms": 93,
"refresh_cycles": 232,
"sources_count": 118,
"top_proxies": ["..."]
},
"ffmpeg_available": true,
"cookies_configured": true,
"instagram_sessions": 3,
"instagrapi_available": false,
"download_methods": ["instaloader", "instagrapi", "yt-dlp", "cobalt", "facebook-direct"],
"redis_connected": false,
"wasabi_configured": false,
"wasabi_bucket": null,
"platform_info": {
"system": "Linux",
"release": "6.8.0-106-generic",
"python_version": "3.12.0",
"machine": "x86_64"
}
}
Returns the currently available downloader cascade and the readiness of each method (instaloader, instagrapi, yt-dlp).
curl https://medialoader.69media.pro/api/v1/methods \
-H "X-API-Key: YOUR_API_KEY"
Returns current proxy pool metrics: pool size, verified count, speed, blacklisted count, and refresh state.
curl https://medialoader.69media.pro/api/v1/proxy-stats \
-H "X-API-Key: YOUR_API_KEY"
Checks the configured Cobalt instance and returns its availability, version, and supported services list.
curl https://medialoader.69media.pro/api/v1/cobalt-status \
-H "X-API-Key: YOUR_API_KEY"
Discovers all configured Ollama endpoints and reports model availability for extraction and AML workloads.
curl https://medialoader.69media.pro/api/v1/ollama-status \
-H "X-API-Key: YOUR_API_KEY"
Runs extended checks for yt-dlp, ffmpeg, and a sample extractor probe. Requires a valid API key. Returns 403 if no API key is configured.
curl https://medialoader.69media.pro/api/v1/debug \
-H "X-API-Key: YOUR_API_KEY"
Cookie Endpoints
Cookies enable authenticated access to platforms like Instagram, TikTok, Twitter, YouTube, Facebook, and Pinterest.
Shows whether the primary Instagram cookie file exists and contains a usable sessionid.
curl https://medialoader.69media.pro/api/v1/cookies/status \
-H "X-API-Key: YOUR_API_KEY"
Returns file presence, auth-readiness, and cookie-name previews for every supported platform.
curl https://medialoader.69media.pro/api/v1/cookies/all \
-H "X-API-Key: YOUR_API_KEY"
Creates or replaces the primary Instagram Netscape cookie file from manually supplied values.
| Field | Type | Description |
|---|---|---|
| sessionidrequired | string | Instagram sessionid cookie value (min 10 chars) |
| csrftokenoptional | string | Instagram csrftoken cookie |
| ds_user_idoptional | string | Instagram ds_user_id cookie |
curl -X POST https://medialoader.69media.pro/api/v1/cookies/manual \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "sessionid": "12345678%3AAbCdEfGhIjKlMn%3A12", "csrftoken": "abcdef1234567890abcdef1234567890", "ds_user_id": "12345678" }'
Persists cookies for any supported platform in Netscape format. Supported platforms: instagram, twitter, tiktok, facebook, youtube, pinterest.
| Field | Type | Description |
|---|---|---|
| platformrequired | string | Platform identifier |
| cookiesrequired | object | Map of cookie name → value |
curl -X POST https://medialoader.69media.pro/api/v1/cookies/platform \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "platform": "tiktok", "cookies": { "sessionid": "abc123def456", "tt_webid_v2": "7123456789012345678" } }'
Attempts to locate an installed browser (Chrome, Firefox, Edge) with an active Instagram session and exports its cookies into the server cookie store. No request body needed.
curl -X POST https://medialoader.69media.pro/api/v1/cookies/import-from-browser \
-H "X-API-Key: YOUR_API_KEY"
Session Endpoints
Multi-account Instagram session management backed by Netscape cookie files.
Returns all configured Instagram cookie sessions and their status (availability, fail count, blocked time).
curl https://medialoader.69media.pro/api/v1/sessions \
-H "X-API-Key: YOUR_API_KEY"
Reloads all Instagram sessions from cookie files on disk. Useful after manually adding new session files.
curl -X POST https://medialoader.69media.pro/api/v1/sessions/reload \
-H "X-API-Key: YOUR_API_KEY"
Adds a named session from cookies/sessions/{name}.txt into the in-memory Instagram session pool.
| Query param | Type | Description |
|---|---|---|
| namerequired | string | Session name (a-z, A-Z, 0-9, _, -; max 64 chars). Must match filename in cookies/sessions/ |
curl -X POST "https://medialoader.69media.pro/api/v1/sessions/add?name=account2" \ -H "X-API-Key: YOUR_API_KEY"
Auth (Browser Automation) Endpoints
Interactive Playwright-backed browser sessions for establishing authenticated platform sessions. Flow: start → interact via action → check status → finish (saves cookies).
Launches a Playwright browser on the login page for the selected platform. Returns a session_id and a base64-encoded screenshot.
| Field | Type | Description |
|---|---|---|
| platformrequired | string | instagram, facebook, twitter, tiktok, youtube, pinterest |
curl -X POST https://medialoader.69media.pro/api/v1/auth/start \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"platform": "instagram"}'
Returns the latest base64-encoded PNG screenshot and detected authentication cookie presence for the active session.
curl https://medialoader.69media.pro/api/v1/auth/screenshot/SESSION_ID \
-H "X-API-Key: YOUR_API_KEY"
Executes a browser action inside the active Playwright session and returns the updated state with a new screenshot.
| Field | Type | Description |
|---|---|---|
| session_idrequired | string | Auth-session identifier |
| actionrequired | string | click, type, press, goto, scroll, wait, clear_and_type, fill |
| selectoroptional | string | CSS selector for click, type, fill |
| textoptional | string | Text for type / fill |
| keyoptional | string | Key for press (default: Enter) |
| urloptional | string | URL for goto (http/https only) |
| directionoptional | string | up | down for scroll |
| msoptional | integer | Milliseconds for wait (100–5000) |
curl -X POST https://medialoader.69media.pro/api/v1/auth/action \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "session_id": "SESSION_ID", "action": "fill", "selector": "input[name=username]", "text": "myaccount" }'
Inspects the current browser session and reports whether the required cookies for the selected platform are present. Returns authenticated: true/false and per-cookie presence flags.
curl https://medialoader.69media.pro/api/v1/auth/status/SESSION_ID \
-H "X-API-Key: YOUR_API_KEY"
Extracts cookies from the browser, saves them to the platform cookie store, and closes the Playwright session. Returns saved: true/false and the file path.
curl -X POST https://medialoader.69media.pro/api/v1/auth/finish/SESSION_ID \
-H "X-API-Key: YOUR_API_KEY"
Stops the Playwright session and discards any unsaved browser state.
curl -X POST https://medialoader.69media.pro/api/v1/auth/close/SESSION_ID \
-H "X-API-Key: YOUR_API_KEY"
Returns all currently active interactive authorization sessions with their platform, age, and current URL.
curl https://medialoader.69media.pro/api/v1/auth/sessions \
-H "X-API-Key: YOUR_API_KEY"
Admin Endpoints
Admin endpoints require authentication via a session token. Obtain it from POST /api/v1/admin/login and pass it in X-Admin-Token header on all subsequent admin calls.
API key management requires the superadmin role. User management requires admin or superadmin.
| Field | Type | Description |
|---|---|---|
| emailrequired | string | Admin account email |
| passwordrequired | string | Admin password |
Returns: {"token": "...", "user": {"id": 1, "email": "...", "role": "superadmin"}}
curl -X POST https://medialoader.69media.pro/api/v1/admin/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@example.com","password":"secret"}'
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"email": "admin@example.com",
"role": "superadmin"
}
}
Deletes the current admin session token. Pass X-Admin-Token header. Returns {"status": "ok"}.
curl -X POST https://medialoader.69media.pro/api/v1/admin/logout \
-H "X-Admin-Token: ADMIN_TOKEN"
Returns the user bound to the supplied X-Admin-Token session. Response: {"user": {"id": 1, "email": "...", "role": "..."}}.
curl https://medialoader.69media.pro/api/v1/admin/me \
-H "X-Admin-Token: ADMIN_TOKEN"
Returns all users. Requires admin or superadmin role. Response: {"users": [...]}.
curl https://medialoader.69media.pro/api/v1/admin/users \
-H "X-Admin-Token: ADMIN_TOKEN"
Creates a new user in the admin database. Requires superadmin role.
| Field | Type | Description |
|---|---|---|
| emailrequired | string | New user email |
| passwordrequired | string | Password (min 6 characters) |
| roleoptional | string | user (default), admin, superadmin |
curl -X POST https://medialoader.69media.pro/api/v1/admin/users \ -H "X-Admin-Token: ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"email":"dev@example.com","password":"securepass","role":"admin"}'
{
"user": {
"id": 42,
"email": "dev@example.com",
"role": "admin"
}
}
Returns whether API key authentication is required and the current active key. Superadmins see the full key; admins see a masked version.
curl https://medialoader.69media.pro/api/v1/admin/settings/api-key \
-H "X-Admin-Token: ADMIN_TOKEN"
{
"api_key_required": true,
"api_key": "YOUR_API_KEY",
"api_key_source": "database"
}
Toggle whether clients must supply an API key. When enabling, a key is auto-generated if none exists. Requires superadmin role.
| Field | Type | Description |
|---|---|---|
| requiredrequired | boolean | true to require API key, false to allow public access |
curl -X PUT https://medialoader.69media.pro/api/v1/admin/settings/api-key \ -H "X-Admin-Token: ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"required": true}'
curl -X PUT https://medialoader.69media.pro/api/v1/admin/settings/api-key \ -H "X-Admin-Token: ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"required": false}'
Generates a new random API key and replaces the current one. All existing clients must update their key. Requires superadmin role.
curl -X POST https://medialoader.69media.pro/api/v1/admin/settings/api-key/regenerate \
-H "X-Admin-Token: ADMIN_TOKEN"
{
"api_key": "YOUR_NEW_API_KEY",
"message": "API key regenerated. Update key in all clients."
}
Personal API Keys
Each admin user can generate their own API keys (prefix mdl_). These keys are accepted in the X-API-Key header for all /api/* endpoints. Superadmins can additionally manage keys for any user.
Returns all active API keys for the currently authenticated user. Requires X-Admin-Token.
curl https://medialoader.69media.pro/api/v1/admin/user/api-keys \
-H "X-Admin-Token: ADMIN_TOKEN"
{
"keys": [
{
"id": 1,
"key_prefix": "mdl_tMWmNiaF",
"label": "production",
"created_at": "2026-05-13T10:00:00+00:00",
"last_used_at": "2026-05-13T11:30:00+00:00"
}
]
}
Generates a new API key for the current user. The full key is returned once only — save it immediately. Max 10 active keys per user.
curl -X POST https://medialoader.69media.pro/api/v1/admin/user/api-keys \ -H "X-Admin-Token: ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"label": "my-integration"}'
{
"key": "mdl_tMWmNiaFKyJbo5kmXr...",
"record": {
"id": 1,
"key_prefix": "mdl_tMWmNiaF",
"label": "my-integration",
"created_at": "2026-05-13T10:00:00+00:00",
"last_used_at": null
}
}
Use the returned key in API calls:
curl https://medialoader.69media.pro/api/v1/files \
-H "X-API-Key: mdl_tMWmNiaFKyJbo5kmXr..."Permanently deactivates the specified key. Only the owning user can revoke their own keys.
curl -X DELETE https://medialoader.69media.pro/api/v1/admin/user/api-keys/1 \
-H "X-Admin-Token: ADMIN_TOKEN"Superadmin: Manage all keys
Superadmins can view all keys system-wide, create keys for any user, and revoke any key.
Returns every active personal API key across all users. Requires superadmin role.
curl https://medialoader.69media.pro/api/v1/admin/all-api-keys \
-H "X-Admin-Token: SUPERADMIN_TOKEN"Generates a new API key for the specified user. Requires superadmin role. Full key shown once only.
curl -X POST https://medialoader.69media.pro/api/v1/admin/all-api-keys \ -H "X-Admin-Token: SUPERADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user_id": 2, "label": "client-integration"}'
Permanently deactivates any API key regardless of owner. Requires superadmin role.
curl -X DELETE https://medialoader.69media.pro/api/v1/admin/all-api-keys/5 \
-H "X-Admin-Token: SUPERADMIN_TOKEN"Integration Guides
Python — Full Integration Example
import time, requests class MediaDownloaderClient: def __init__(self, base_url: str, api_key: str = ""): self.base = base_url.rstrip("/") + "/api/v1" self.headers = {"Content-Type": "application/json"} if api_key: self.headers["X-API-Key"] = api_key def download(self, url: str, quality: str = "max", poll_interval: float = 3) -> dict: r = requests.post(f"{self.base}/download", json={"url": url, "quality": quality}, headers=self.headers) r.raise_for_status() task_id = r.json()["id"] return self._poll(task_id, poll_interval) def batch_download(self, urls: list, quality: str = "max", poll_interval: float = 3) -> list: r = requests.post(f"{self.base}/batch-download", json={"urls": urls, "quality": quality}, headers=self.headers) r.raise_for_status() ids = [t["id"] for t in r.json()["tasks"]] return [self._poll(tid, poll_interval) for tid in ids] def get_file(self, path: str) -> bytes: # path is a relative string like "tiktok/user/video.mp4" r = requests.get(f"{self.base}/files/{path}", headers=self.headers, allow_redirects=True) r.raise_for_status() return r.content def _poll(self, task_id: str, interval: float) -> dict: while True: task = requests.get(f"{self.base}/tasks/{task_id}", headers=self.headers).json() if task["status"] in ("completed", "error"): return task time.sleep(interval) # Usage client = MediaDownloaderClient( base_url="https://medialoader.69media.pro", api_key="YOUR_API_KEY" ) task = client.download("https://www.tiktok.com/@user/video/7123456789") if task["status"] == "completed": # task["files"] is a list of relative path strings for f in task["files"]: data = client.get_file(f) filename = f.split("/")[-1] open(filename, "wb").write(data) print(f"Saved: {filename}")
JavaScript / Node.js — Full Integration Example
class MediaDownloaderClient { constructor(baseUrl, apiKey = "") { this.base = baseUrl.replace(/\/$/, "") + "/api/v1"; this.headers = { "Content-Type": "application/json", ...(apiKey && { "X-API-Key": apiKey }) }; } async download(url, quality = "max") { const { id } = await this._post("/download", { url, quality }); return await this._poll(id); } async batchDownload(urls, quality = "max") { const { tasks } = await this._post("/batch-download", { urls, quality }); return Promise.all(tasks.map(t => this._poll(t.id))); } // files in task are relative path strings, encode them for URL use getFileUrl(filePath) { return `${this.base}/files/${encodeURIComponent(filePath)}`; } async _poll(taskId, interval = 3000) { let task; do { await new Promise(r => setTimeout(r, interval)); task = await fetch(`${this.base}/tasks/${taskId}`, { headers: this.headers }).then(r => r.json()); } while (!["completed", "error"].includes(task.status)); return task; } async _post(path, body) { const res = await fetch(this.base + path, { method: "POST", headers: this.headers, body: JSON.stringify(body) }); if (!res.ok) throw new Error(await res.text()); return res.json(); } } // Usage const client = new MediaDownloaderClient("https://medialoader.69media.pro", "YOUR_API_KEY"); const task = await client.download("https://www.instagram.com/p/ABC123/"); // task.files is an array of relative path strings console.log(task.files?.map(f => client.getFileUrl(f)));
API Key Setup Workflow
# 1. Login as superadmin TOKEN=$(curl -s -X POST https://medialoader.69media.pro/api/v1/admin/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@example.com","password":"secret"}' | jq -r '.token') # 2. Enable API key requirement (auto-generates a key) curl -X PUT https://medialoader.69media.pro/api/v1/admin/settings/api-key \ -H "X-Admin-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{"required": true}' # 3. View the current key curl https://medialoader.69media.pro/api/v1/admin/settings/api-key \ -H "X-Admin-Token: $TOKEN" # 4. Rotate the key (all clients must update) curl -X POST https://medialoader.69media.pro/api/v1/admin/settings/api-key/regenerate \ -H "X-Admin-Token: $TOKEN" # 5. Disable key requirement (public access) curl -X PUT https://medialoader.69media.pro/api/v1/admin/settings/api-key \ -H "X-Admin-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{"required": false}'
Interactive docs: Swagger UI → | OpenAPI spec: openapi.json →