Overview
A self-hosted image optimization & transformation API. You upload originals once, then request any size/format on demand through a URL — resized, compressed, converted to WebP/AVIF, cached at the edge, and served with long-lived cache headers.
- Organize media in nested folders per client.
- Get delivery URLs via signed URLs (any transform) or named presets (no signature).
- Delivery URLs are public to view — drop them straight into an
<img>.
Base URL
https://api-images.amr-dev.onlineAll management endpoints below are relative to this base.
Authentication
Programmatic calls to /api/v1/* require your API key, sent as an X-Api-Key header. Create and manage keys in the dashboard → API Keys. Keep keys secret — they act on your account.
X-Api-Key: isk_your_api_key_here/t/…) need no key — they’re authorized by the signature or a preset, so anyone with the URL can view the image.Quick start
curl -X POST https://api-images.amr-dev.online/api/v1/images \
-H "X-Api-Key: YOUR_API_KEY" \
-F "folder=products/shoes" \
-F "file=@photo.jpg"The folder path is created automatically if it doesn’t exist. Omit folder to upload to the root. The response includes a ready-to-use thumbnailUrl and the image id.
curl -X POST https://api-images.amr-dev.online/api/v1/sign \
-H "X-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"imageId":"IMAGE_ID","transform":"w_600,f_webp,q_80"}'
# → { "url": "https://api-images.amr-dev.online/t/<clientId>/<sig>/w_600,f_webp,q_80/IMAGE_ID.webp", ... }<img src="https://api-images.amr-dev.online/t/<clientId>/<sig>/w_600,f_webp,q_80/IMAGE_ID.webp" alt="" />Tip: in the dashboard, click any image to copy a public URL instantly — no code needed.
Images
/api/v1/imagesUpload (multipart). Fields: file (required), folder (optional path, auto-created).
/api/v1/images?folder=&q=&page=1&pageSize=24List media. Filter by folder, search by name (q). Returns { items, total, page, pageSize }.
/api/v1/images/:idGet one image's metadata.
/api/v1/images/:idReplace the file (multipart: file). Keeps the same id/URLs; old cached variants are purged.
/api/v1/images/:idDelete the image and all its cached variants.
{
"id": "a124…",
"originalName": "photo.jpg",
"folder": "products/shoes",
"format": "jpeg",
"width": 1200, "height": 800, "bytes": 34567,
"deliveryBase": "/t/<clientId>",
"thumbnailUrl": "https://api-images.amr-dev.online/t/<clientId>/<sig>/w_240,f_webp,q_75/a124….webp"
}Folders
/api/v1/foldersGet the folder tree.
/api/v1/foldersCreate a nested folder. Body: { "path": "a/b/c" }.
/api/v1/folders/:idRename a folder. Body: { "name": "newname" }.
/api/v1/folders/:idDelete a folder (and its sub-folders + images).
Search
/api/v1/search?q=shoesSearch your media by image name and folder name. Returns { images, folders }.
Delivery URLs
Every image URL is one of two kinds — both are public to view:
GET /t/<clientId>/<sig>/<transform>/<imageId>.<ext>Mint one with POST /api/v1/sign (below).
GET /t/<clientId>/preset:<name>/<imageId>.<ext>Define a preset once, then build URLs client-side for any image — no signing call needed.
Sign a URL
/api/v1/signBody: { "imageId": "…", "transform": "w_600,f_webp,q_80" }. Returns { url, canonical, format }.
transform is optional — omit it to get the full-size image (WebP by default).
Presets
/api/v1/presetsList your presets.
/api/v1/presetsCreate a preset. Body: { "name": "thumb", "params": "w_240,c_fill,f_webp,q_75" }.
/api/v1/presets/:idDelete a preset.
Transform parameters
A transform is a comma-separated list of key_value segments, e.g. w_600,h_400,c_cover,f_webp,q_80.
| Param | Meaning | Values |
|---|---|---|
w_ | Width (px) | e.g. w_600 |
h_ | Height (px) | e.g. h_400 |
c_ | Fit / crop mode | fit · fill · cover · contain · inside |
f_ | Output format | webp · jpeg · png · avif · auto |
q_ | Quality | 1–100 (e.g. q_80) |
dpr_ | Device pixel ratio | e.g. dpr_2 (multiplies w/h) |
Width-only (e.g. w_600) keeps the aspect ratio. f_auto resolves to WebP.
Examples
const fd = new FormData();
fd.append('file', fileInput.files[0]);
fd.append('folder', 'products'); // optional
const res = await fetch('https://api-images.amr-dev.online/api/v1/images', {
method: 'POST',
headers: { 'X-Api-Key': 'YOUR_API_KEY' }, // do NOT set Content-Type for FormData
body: fd,
});
const image = await res.json();
console.log(image.id, image.thumbnailUrl);const res = await fetch('https://api-images.amr-dev.online/api/v1/sign', {
method: 'POST',
headers: { 'X-Api-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ imageId, transform: 'w_800,f_webp,q_82' }),
});
const { url } = await res.json(); // public, embeddable