API Documentation
Integrate AI-powered image upscaling into your applications with a simple REST API.
Quick Start
Upscale an image in three steps. Choose your language:
Get your API key
Sign up and subscribe to a paid plan to get your API key from the dashboard. Use it as a Bearer token in all requests:
Authorization: Bearer YOUR_API_TOKEN
Upload an image for upscaling
curl -X POST https://www.upscale-media.ai/api/images/upscale \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -F "image=@photo.jpg" \ -F "scale_factor=2" # Returns 202 with image ID in data.id
response = requests.post(
"https://www.upscale-media.ai/api/images/upscale",
headers={"Authorization": f"Bearer {token}"},
files={"image": open("photo.jpg", "rb")},
data={"scale_factor": 2}
)
image_id = response.json()["data"]["id"]
const formData = new FormData();
formData.append("image", fileInput.files[0]);
formData.append("scale_factor", "2");
const upload = await fetch("https://www.upscale-media.ai/api/images/upscale", {
method: "POST",
headers: { "Authorization": `Bearer ${token}` },
body: formData
});
const imageId = (await upload.json()).data.id;
$response = Http::withToken($token)
->attach('image', file_get_contents('photo.jpg'), 'photo.jpg')
->post('https://www.upscale-media.ai/api/images/upscale', [
'scale_factor' => 2,
]);
$imageId = $response->json('data.id');
Poll until complete, then download
# Poll for completion
while true; do
STATUS=$(curl -s https://www.upscale-media.ai/api/images/$IMAGE_ID \
-H "Authorization: Bearer YOUR_API_TOKEN" \
| jq -r '.data.status')
echo "Status: $STATUS"
[ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ] && break
sleep 3
done
# Get the download URL
curl -s https://www.upscale-media.ai/api/images/$IMAGE_ID/download \
-H "Authorization: Bearer YOUR_API_TOKEN" \
| jq -r '.data.download_url'
import time
# Poll for completion
while True:
result = requests.get(
f"https://www.upscale-media.ai/api/images/{image_id}",
headers={"Authorization": f"Bearer {token}"}
).json()
status = result["data"]["status"]
print(f"Status: {status}")
if status in ("completed", "failed"):
break
time.sleep(3)
# Get the download URL
download = requests.get(
f"https://www.upscale-media.ai/api/images/{image_id}/download",
headers={"Authorization": f"Bearer {token}"}
).json()
print(download["data"]["download_url"])
// Poll for completion
const poll = async (id) => {
while (true) {
const res = await fetch(`https://www.upscale-media.ai/api/images/${id}`, {
headers: { "Authorization": `Bearer ${token}` }
});
const { data } = await res.json();
console.log(`Status: ${data.status}`);
if (data.status === "completed" || data.status === "failed") {
return data;
}
await new Promise(r => setTimeout(r, 3000));
}
};
const image = await poll(imageId);
// Get the download URL
const dl = await fetch(`https://www.upscale-media.ai/api/images/${imageId}/download`, {
headers: { "Authorization": `Bearer ${token}` }
});
const { data: dlData } = await dl.json();
console.log(dlData.download_url);
// Poll for completion
do {
sleep(3);
$result = Http::withToken($token)
->get("https://www.upscale-media.ai/api/images/{$imageId}")
->json();
$status = $result['data']['status'];
echo "Status: {$status}\n";
} while (!in_array($status, ['completed', 'failed']));
// Get the download URL
$download = Http::withToken($token)
->get("https://www.upscale-media.ai/api/images/{$imageId}/download")
->json();
echo $download['data']['download_url'];
Overview
The Upscale Media API lets you integrate AI-powered image upscaling into your applications. Upload images, poll for results, and download enhanced versions — all via simple REST endpoints.
Response Format
All responses return JSON with a consistent envelope:
{
"success": true,
"message": "Human-readable status message",
"data": { ... }
}
Error responses include success: false and may include an errors object for validation failures.
Authentication
Authenticate by including a Bearer token in the Authorization header. Obtain a token by registering or logging in via the API, or from your
dashboard after signing up.
Authorization: Bearer YOUR_API_TOKEN
/api/auth/register
Public
Create a new account and receive a Bearer token. A verification email is sent automatically.
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Full name (max 255 characters) |
| string | Yes | Valid email address (unique) | |
| password | string | Yes | Min 8 characters, mixed case, numbers |
| password_confirmation | string | Yes | Must match password |
| device_name | string | No | Label for the token (defaults to user agent) |
{
"success": true,
"message": "Registration successful. Please verify your email to access all features.",
"data": {
"user": {
"id": 1,
"name": "Jane Smith",
"email": "jane@example.com",
"email_verified_at": null,
"profile_photo_url": "https://...",
"created_at": "2026-02-15T12:00:00.000000Z",
"updated_at": "2026-02-15T12:00:00.000000Z",
"pricing_plan": {
"id": 1,
"name": "Free",
"slug": "free"
}
},
"token": "1|abc123...",
"token_type": "Bearer"
}
}
/api/auth/login
Public
Authenticate with email and password. Returns a Bearer token. Requires a verified email address.
curl -X POST https://www.upscale-media.ai/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "jane@example.com", "password": "your-password"}'
{
"success": true,
"message": "Login successful",
"data": {
"user": { ... },
"token": "2|xyz789...",
"token_type": "Bearer"
}
}
/api/auth/logout
Authenticated
Revoke the current API token.
{"success": true, "message": "Logout successful"}
/api/auth/revoke-all
Authenticated
Revoke all API tokens for your account. Use this if a token is compromised.
{"success": true, "message": "All tokens revoked successfully"}
Images
Upload images for AI upscaling, check processing status, and download enhanced results. Upscaling is asynchronous — submit an image, then poll for completion.
/api/images/upscale
Authenticated
Submit an image for upscaling. Returns immediately with a 202 Accepted status while processing happens in the background.
Body Parameters (multipart/form-data)
| Parameter | Type | Required | Description |
|---|---|---|---|
| image | file | Yes | JPEG, PNG, WebP, BMP, TIFF, or GIF. Max 10MB. |
| scale_factor | integer | No | 2, 3, or 4. Defaults to 2. Cannot be used with target_width/target_height. |
| target_width | integer | No | Exact output width in pixels (1–16384). If target_height is omitted, it is calculated automatically to preserve aspect ratio. Cannot be used with scale_factor. |
| target_height | integer | No | Exact output height in pixels (1–16384). If target_width is omitted, it is calculated automatically to preserve aspect ratio. Cannot be used with scale_factor. |
Sizing options: Use scale_factor for simple 2x/3x/4x upscaling, or specify a target resolution. You can provide both target_width and target_height for exact dimensions, or just one — the other will be calculated automatically to preserve the original aspect ratio. The target must be larger than the original and achievable within your plan's max scale (e.g., 4x).
curl -X POST https://www.upscale-media.ai/api/images/upscale \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -F "image=@photo.jpg" \ -F "scale_factor=2"
import requests
response = requests.post(
"https://www.upscale-media.ai/api/images/upscale",
headers={"Authorization": "Bearer YOUR_API_TOKEN"},
files={"image": open("photo.jpg", "rb")},
data={"scale_factor": 2}
)
print(response.json())
const formData = new FormData();
formData.append("image", fileInput.files[0]);
formData.append("scale_factor", "2");
const response = await fetch("https://www.upscale-media.ai/api/images/upscale", {
method: "POST",
headers: { "Authorization": "Bearer YOUR_API_TOKEN" },
body: formData
});
const data = await response.json();
$response = Http::withToken('YOUR_API_TOKEN')
->attach('image', file_get_contents('photo.jpg'), 'photo.jpg')
->post('https://www.upscale-media.ai/api/images/upscale', [
'scale_factor' => 2,
]);
$data = $response->json();
{
"success": true,
"message": "Image uploaded and queued for processing",
"data": {
"id": 42,
"original_filename": "photo.jpg",
"original_size": 2048576,
"original_size_human": "2 MB",
"original_dimensions": null,
"status": "pending",
"scale_factor": 2,
"target_width": null,
"target_height": null,
"api_request": true,
"created_at": "2026-02-15T12:00:00.000000Z",
"updated_at": "2026-02-15T12:00:00.000000Z"
}
}
Tip: After uploading, poll GET /api/images/{id} every few seconds until status is completed or failed.
/api/images/{id}
Authenticated
Get the status and details of a specific image. Use this to poll for processing completion.
curl https://www.upscale-media.ai/api/images/42 \ -H "Authorization: Bearer YOUR_API_TOKEN"
response = requests.get(
"https://www.upscale-media.ai/api/images/42",
headers={"Authorization": "Bearer YOUR_API_TOKEN"}
)
print(response.json())
const response = await fetch("https://www.upscale-media.ai/api/images/42", {
headers: { "Authorization": "Bearer YOUR_API_TOKEN" }
});
const data = await response.json();
$response = Http::withToken('YOUR_API_TOKEN')
->get('https://www.upscale-media.ai/api/images/42');
$data = $response->json();
{
"success": true,
"message": "Image retrieved successfully",
"data": {
"id": 42,
"original_filename": "photo.jpg",
"original_path": "images/originals/abc123.jpg",
"upscaled_path": "images/upscaled/abc123.jpg",
"original_size": 2048576,
"upscaled_size": 8194304,
"original_size_human": "2 MB",
"upscaled_size_human": "7.81 MB",
"original_dimensions": "1920x1080",
"upscaled_dimensions": "3840x2160",
"original_dimensions_formatted": "1920 x 1080",
"upscaled_dimensions_formatted": "3840 x 2160",
"status": "completed",
"scale_factor": 2,
"target_width": null,
"target_height": null,
"processing_time": 4.82,
"api_request": true,
"download_url": "https://...",
"created_at": "2026-02-15T12:00:00.000000Z",
"updated_at": "2026-02-15T12:00:05.000000Z"
}
}
Image Statuses
/api/images
Authenticated
List all your images with pagination. Newest first.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | integer | 1 | Page number |
| per_page | integer | 15 | Items per page (max 100) |
| status | string | all | Filter: pending, processing, completed, or failed |
curl "https://www.upscale-media.ai/api/images?per_page=10&status=completed" \ -H "Authorization: Bearer YOUR_API_TOKEN"
{
"success": true,
"message": "Images retrieved successfully",
"data": [ { ... }, { ... } ],
"meta": {
"current_page": 1,
"last_page": 3,
"per_page": 10,
"total": 27
},
"links": {
"first": "https://www.upscale-media.ai/api/images?page=1",
"last": "https://www.upscale-media.ai/api/images?page=3",
"prev": null,
"next": "https://www.upscale-media.ai/api/images?page=2"
}
}
/api/images/{id}/download
Authenticated
Get a download URL for a completed image. Returns an error if the image is still processing.
{
"success": true,
"message": "Download URL generated successfully",
"data": {
"download_url": "https://...",
"filename": "photo.jpg"
}
}
/api/images/{id}
Authenticated
Permanently delete an image and its upscaled version.
{"success": true, "message": "Image deleted successfully"}
Batches
Upload multiple images at once for batch upscaling. Each image is processed independently and you can track overall batch progress.
/api/batches
Authenticated · Pro/Enterprise
Upload up to 20 images in a single request. Returns immediately with a 202 Accepted status while all images are queued for processing.
Body Parameters (multipart/form-data)
| Parameter | Type | Required | Description |
|---|---|---|---|
| images[] | file[] | Yes | 1-20 image files. JPEG, PNG, WebP, BMP, TIFF, or GIF. Max 10MB per file. |
| scale_factor | integer | No | 2, 3, or 4. Applied to all images. Defaults to 2. Cannot be used with target dimensions. |
| target_width | integer | No | Exact output width in pixels (1–16384). Applied to all images. If target_height is omitted, aspect ratio is preserved. |
| target_height | integer | No | Exact output height in pixels (1–16384). Applied to all images. If target_width is omitted, aspect ratio is preserved. |
| name | string | No | Optional label for this batch (max 255 characters). |
curl -X POST https://www.upscale-media.ai/api/batches \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -F "images[]=@photo1.jpg" \ -F "images[]=@photo2.jpg" \ -F "images[]=@photo3.jpg" \ -F "scale_factor=2" \ -F "name=Product photos"
{
"success": true,
"message": "Batch created and images queued for processing",
"data": {
"id": 7,
"name": "Product photos",
"status": "pending",
"total_images": 3,
"completed_images": 0,
"failed_images": 0,
"scale_factor": 2,
"progress": 0,
"images": [
{ "id": 101, "batch_id": 7, "original_filename": "photo1.jpg", "status": "pending", ... },
{ "id": 102, "batch_id": 7, "original_filename": "photo2.jpg", "status": "pending", ... },
{ "id": 103, "batch_id": 7, "original_filename": "photo3.jpg", "status": "pending", ... }
],
"created_at": "2026-02-15T12:00:00.000000Z",
"updated_at": "2026-02-15T12:00:00.000000Z",
"completed_at": null
}
}
Tip: Poll GET /api/batches/{id} to track overall progress. The progress field shows completion percentage. All images must fit within your remaining monthly quota.
/api/batches/{id}
Authenticated · Pro/Enterprise
Get the status and details of a batch, including all its images. Use this to poll for batch completion.
curl https://www.upscale-media.ai/api/batches/7 \ -H "Authorization: Bearer YOUR_API_TOKEN"
{
"success": true,
"message": "Batch retrieved successfully",
"data": {
"id": 7,
"name": "Product photos",
"status": "completed",
"total_images": 3,
"completed_images": 3,
"failed_images": 0,
"scale_factor": 2,
"progress": 100,
"images": [
{ "id": 101, "status": "completed", "download_url": "https://...", ... },
{ "id": 102, "status": "completed", "download_url": "https://...", ... },
{ "id": 103, "status": "completed", "download_url": "https://...", ... }
],
"created_at": "2026-02-15T12:00:00.000000Z",
"updated_at": "2026-02-15T12:00:05.000000Z",
"completed_at": "2026-02-15T12:00:05.000000Z"
}
}
Batch Statuses
/api/batches
Authenticated · Pro/Enterprise
List all your batches with pagination. Newest first.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | integer | 1 | Page number |
| per_page | integer | 15 | Items per page (max 100) |
| status | string | all | Filter: pending, processing, completed, partially_failed, failed, or cancelled |
{
"success": true,
"message": "Batches retrieved successfully",
"data": [ { ... }, { ... } ],
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 2
},
"links": { ... }
}
/api/batches/{id}
Authenticated · Pro/Enterprise
Cancel a pending/processing batch or permanently delete a completed batch. Cancelling marks unfinished images as failed.
{"success": true, "message": "Batch cancelled successfully"}
Account
Manage your profile, check usage quotas, and view subscription details.
/api/user
Authenticated
Get the authenticated user's profile and current plan.
{
"success": true,
"message": "User retrieved successfully",
"data": {
"id": 1,
"name": "Jane Smith",
"email": "jane@example.com",
"email_verified_at": "2026-02-15T12:05:00.000000Z",
"profile_photo_url": "https://...",
"created_at": "2026-02-15T12:00:00.000000Z",
"updated_at": "2026-02-15T12:00:00.000000Z",
"pricing_plan": {
"id": 2,
"name": "Starter",
"slug": "starter"
}
}
}
/api/usage
Authenticated
Check your current month's usage against your plan quota.
{
"success": true,
"message": "Usage statistics retrieved successfully",
"data": {
"plan": "starter",
"image_uploads": {
"used": 42,
"limit": 100,
"remaining": 58,
"unlimited": false,
"exceeded": false,
"percentage": 42.0
},
"features": ["api_access", "priority_support"]
}
}
/api/subscription
Authenticated
Get your current subscription status and plan details.
{
"success": true,
"message": "Subscription details retrieved successfully",
"data": {
"subscription": {
"id": 1,
"type": "default",
"status": "active",
"quantity": 1,
"trial_ends_at": null,
"ends_at": null,
"created_at": "2026-01-01T00:00:00.000000Z",
"is_active": true,
"is_on_trial": false,
"is_cancelled": false,
"is_on_grace_period": false
},
"plan": {
"name": "Starter",
"slug": "starter",
"price": 9,
"features": [...],
"limits": [...]
}
}
}
/api/user/tokens
Authenticated
List all your active API tokens.
{
"success": true,
"message": "API tokens retrieved successfully",
"data": {
"tokens": [
{
"id": 1,
"name": "My App",
"abilities": ["images:read", "images:write", "images:delete", "user:read"],
"last_used_at": "2026-02-15T11:30:00.000000Z",
"created_at": "2026-01-15T09:00:00.000000Z"
}
],
"count": 1
}
}
/api/user/tokens/{id}
Authenticated
Revoke a specific API token by its ID.
{"success": true, "message": "Token revoked successfully"}
Rate Limits
API requests are rate-limited based on your plan. Limits reset every hour.
| Plan | Requests / Hour | Images / Month |
|---|---|---|
| Unauthenticated | 10 | — |
| Free | 100 | 2 |
| Starter | 500 | 25 |
| Professional | 2,000 | 250 |
| Enterprise | 10,000 | 1,000 – 12,500 |
Rate Limit Headers
Image endpoints include headers to help you track your upload quota:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Your plan's monthly image quota |
| X-RateLimit-Remaining | Remaining image uploads this month |
Errors
The API uses standard HTTP status codes. Errors return a consistent JSON structure.
{
"success": false,
"message": "Validation failed",
"errors": {
"image": ["The image field is required."],
"scale_factor": ["The scale factor must be between 2 and 4."]
}
}
| Code | Status | Description |
|---|---|---|
| 400 | Bad Request | The request was malformed or image processing failed |
| 401 | Unauthorized | Missing or invalid Bearer token |
| 403 | Forbidden | Email not verified, no API access on plan, subscription expired, or quota exceeded |
| 404 | Not Found | Image or token not found |
| 422 | Validation Error | Invalid input. Check the errors object for field-specific messages. |
| 429 | Too Many Requests | Rate limit exceeded. Slow down or upgrade your plan. |
| 500 | Server Error | Something went wrong on our end. Try again later. |