Production-ready image upload, compression, format conversion, and management. Authenticate with a personal API key from your developer dashboard.
Send your key on every request. Keys are shown masked as ql_live_xxxxxxxx…. Free accounts include one active key; use Reveal key (password required) or Regenerate in the dashboard.
Authorization: Bearer ql_live_YOUR_KEY
POST /api/v1/upload or POST /api/v1/uploads · multipart field file
curl -X POST "https://api.quicklistweb.com/api/v1/uploads?format=webp&quality=80" \ -H "Authorization: Bearer ql_live_YOUR_KEY" \ -F "file=@photo.jpg"
const form = new FormData();
form.append("file", file);
const res = await fetch(`https://api.quicklistweb.com/api/v1/uploads?format=webp&quality=80`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: form,
});
const data = await res.json();{
"success": true,
"url": "https://cdn.example/media/abc/file.webp",
"thumbnail": "https://cdn.example/media/abc/thumb.webp",
"size": 48293,
"original_size": 120394,
"type": "image/webp",
"width": 1200,
"height": 800,
"files": [{ "id": 42, "url": "...", "mime": "image/webp" }]
}201 Created · 401 Invalid key · 422 Validation · 429 Rate / daily limit
Use files[] for batch uploads on the same endpoint.
const form = new FormData();
files.forEach((file) => form.append("files[]", file));
await fetch(`https://api.quicklistweb.com/api/v1/uploads`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: form,
});import axios from "axios";
const form = new FormData();
files.forEach((f) => form.append("files[]", f));
const { data } = await axios.post("https://api.quicklistweb.com/api/v1/uploads", form, {
headers: { Authorization: `Bearer ${process.env.QL_API_KEY}` },
});import requests
files = [("files[]", open("a.jpg", "rb")), ("files[]", open("b.png", "rb"))]
r = requests.post(
"https://api.quicklistweb.com/api/v1/uploads",
headers={"Authorization": "Bearer ql_live_..."},
files=files,
)
print(r.json()){
"success": true,
"files": [
{
"id": 42,
"url": "https://...",
"thumbnail": "https://...",
"size": 48293,
"original_size": 120394,
"mime": "image/webp",
"width": 1200,
"height": 800
}
]
}PUT /api/v1/uploads/{id}/replace — same upload ID, new file, thumbnails regenerated.
export async function PUT(req: Request, { params }: { params: { id: string } }) {
const form = await req.formData();
const upstream = await fetch(`https://api.quicklistweb.com/api/v1/uploads/${params.id}/replace`, {
method: "PUT",
headers: { Authorization: `Bearer ${process.env.QL_API_KEY}` },
body: form,
});
return Response.json(await upstream.json(), { status: upstream.status });
}$ch = curl_init("https://api.quicklistweb.com/api/v1/uploads/42/replace");
curl_setopt_array($ch, [
CURLOPT_PUT => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer ql_live_..."],
CURLOPT_POSTFIELDS => ["file" => new CURLFile("/path/new.jpg")],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);GET /api/v1/uploads?page=1&per_page=20&search=logo
GET /api/v1/uploads/{id}DELETE /api/v1/uploads/{id}Images (JPG, PNG, WebP, GIF) are compressed, EXIF stripped, oversized dimensions scaled down, and thumbnails generated automatically. Optional query params:
format — webp, jpg, pngquality — 10–100 (default 82)width / height — resize before encodeasync function upload(file: File) {
const q = new URLSearchParams({ format: "webp", quality: "80" });
const form = new FormData();
form.append("file", file);
const res = await fetch(`https://api.quicklistweb.com/api/v1/uploads?${q}`, {
method: "POST",
headers: { Authorization: `Bearer ${apiKey}` },
body: form,
});
if (!res.ok) throw new Error((await res.json()).message);
return res.json();
}{
"success": false,
"message": "Daily API upload limit reached.",
"errors": { "file": ["Invalid file type."] }
}| Code | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 404 | Upload not found |
| 422 | Validation failed (mime, size, missing file) |
| 429 | Rate limit or daily upload cap |