Image hosting with an API,
and URLs that just work.
Upload with one request, get back a clean URL, resize and convert on the fly with a query string. Built and hosted by ProSolutionX.
POST /api/v1/assetshttps://cdn.prosolutionx.com/site/name.jpg?w=800&f=webpQuick start
You need an API key. Ask us for one — we create a space for your site and send you a key. It takes a minute.
Upload a file
# slug is optional — leave it out and the filename is used curl -X POST https://cdn.prosolutionx.com/api/v1/assets \ -H "Authorization: Bearer <YOUR_API_KEY>" \ -F "file=@photo.jpg" \ -F "slug=blue-widget-hero" \ -F "alt=Blue widget on a white background"
What comes back
{
"id": 12,
"slug": "blue-widget-hero",
"url": "https://cdn.prosolutionx.com/yoursite/blue-widget-hero.jpg",
"immutableUrl": "https://cdn.prosolutionx.com/yoursite/9f2c…a1.jpg",
"width": 1600, "height": 900,
"size": 184320,
"contentType": "image/jpeg"
}
url is readable and can be renamed — use it in
pages, it is the one search engines like. immutableUrl is the content hash:
it can never point at different bytes, so it is cached forever. Use it for things like
email templates where a URL must never change meaning.
API reference
Base URL https://cdn.prosolutionx.com. Every call takes
Authorization: Bearer <key> (or X-Api-Key).
A key belongs to exactly one site and can only see that site's files.
POST/api/v1/assets
upload
Multipart. Field file is required; slug,
alt and title are optional.
curl -X POST https://cdn.prosolutionx.com/api/v1/assets \ -H "Authorization: Bearer $KEY" \ -F "file=@photo.jpg" -F "slug=my-photo"
Uploading the same bytes twice returns the existing file instead of making a duplicate.
GET/api/v1/assets
list & search
?limit=50 ?cursor=<id> ?q=search
curl -H "Authorization: Bearer $KEY" \ "https://cdn.prosolutionx.com/api/v1/assets?q=widget&limit=20"
GET/api/v1/assets/:id
fetch one
Takes the numeric id or the readable name.
curl -H "Authorization: Bearer $KEY" \
https://cdn.prosolutionx.com/api/v1/assets/blue-widget-heroPATCH/api/v1/assets/:id
rename, alt, title
JSON body. Renaming changes the readable URL; the
immutableUrl is unaffected.
curl -X PATCH https://cdn.prosolutionx.com/api/v1/assets/12 \ -H "Authorization: Bearer $KEY" \ -H "Content-Type: application/json" \ -d '{"slug":"blue-widget-2026","alt":"New caption"}'
If the name is taken, a number is appended rather than failing.
PUT/api/v1/assets/:id
replace the file
Multipart, same as upload. Swaps the bytes and keeps the name, so every page already pointing at that URL picks up the new image.
curl -X PUT https://cdn.prosolutionx.com/api/v1/assets/12 \ -H "Authorization: Bearer $KEY" -F "file=@photo-v2.jpg"
DELETE/api/v1/assets/:id
delete
curl -X DELETE https://cdn.prosolutionx.com/api/v1/assets/12 \
-H "Authorization: Bearer $KEY"GET/api/v1/me
check a key
Returns the site the key belongs to plus its usage. Handy for a health check.
{ "site": "yoursite", "assets": 187, "bytes": 232784691 }Errors
400 | Bad request — missing file, or an invalid slug |
401 | Missing, revoked or unknown API key |
404 | No such file under your site |
413 | File over the 25 MB limit |
415 | File type not accepted |
Every error is JSON: {"error":"…"}.
Delivery & transforms
Delivery needs no key — these are public URLs. Add a query string to get a resized or converted copy; it renders once and is cached from then on.
# the original https://cdn.prosolutionx.com/yoursite/blue-widget-hero.jpg # 800px wide, converted to WebP https://cdn.prosolutionx.com/yoursite/blue-widget-hero.jpg?w=800&f=webp # 400px AVIF at quality 70 https://cdn.prosolutionx.com/yoursite/blue-widget-hero.jpg?w=400&f=avif&q=70
w
Width in pixels. Images are never enlarged beyond their original size.
f
webp avif jpeg
png
q
Quality 1–100, default 82.
Accepted on upload
image/jpeg image/png image/webp image/avif image/gif image/svg+xml application/pdf
Up to 25 MB per file. SVG and PDF are stored and served as-is — they are not resized.
Client libraries
Small, dependency-light helpers for the common languages. Each one already has this server's address built in — download, drop in, add your key.
Node, in three lines
import CdnClient from './cdn-client.mjs' const cdn = new CdnClient({ apiKey: process.env.CDN_API_KEY }) const asset = await cdn.upload('./photo.jpg', { slug: 'blue-widget-hero' }) console.log(asset.url) // https://cdn.prosolutionx.com/yoursite/blue-widget-hero.jpg
Need a key?
Tell us the site you want to host images for and we will set it up and send you a key. Each site gets its own URL prefix, its own keys and its own usage.