tomss3

A self-hosted image hosting and resizing API. Upload images from any app, get back unique URLs that serve optimized, resized versions on the fly.

Base URL: https://imgs.modscape.com

Authentication

Upload and delete endpoints require a Bearer token in the Authorization header. Image serving (GET) is public with no auth required.

Authorization: Bearer YOUR_API_KEY

Endpoints

MethodRouteAuthDescription
POST/uploadYesUpload an image
GET/:idNoServe original image (max 2400px wide)
GET/:id/:widthNoServe image at a specific pixel width
DELETE/:idYesDelete an image and all its resized versions

Upload an Image

Send a multipart/form-data POST with the image in a field named file. Max file size depends on the server's PHP configuration (typically 2–50 MB).

curl

curl -X POST https://imgs.modscape.com/upload \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@/path/to/photo.jpg"

JavaScript (Node.js)

const form = new FormData();
form.append('file', fs.createReadStream('/path/to/photo.jpg'));

const res = await fetch('https://imgs.modscape.com/upload', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
  body: form
});
const data = await res.json();

JavaScript (Browser)

// Given an <input type="file"> element:
const file = inputElement.files[0];
const form = new FormData();
form.append('file', file);

const res = await fetch('https://imgs.modscape.com/upload', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
  body: form
});
const data = await res.json();
// data.id       → "a7xK9mPq2w"
// data.original → "https://imgs.modscape.com/a7xK9mPq2w"
// data.sizes    → { 200: "https://...200", 400: "https://...400", ... }

Response

{
  "id": "a7xK9mPq2w",
  "original": "https://imgs.modscape.com/a7xK9mPq2w",
  "sizes": {
    "200": "https://imgs.modscape.com/a7xK9mPq2w/200",
    "400": "https://imgs.modscape.com/a7xK9mPq2w/400",
    "800": "https://imgs.modscape.com/a7xK9mPq2w/800",
    "1200": "https://imgs.modscape.com/a7xK9mPq2w/1200",
    "1600": "https://imgs.modscape.com/a7xK9mPq2w/1600"
  }
}
Note: The sizes object only includes widths smaller than the uploaded image. If you upload a 600px wide image, you will only get 200 and 400 in sizes.

Serve an Image

Images are served publicly. No authentication needed. Use the image ID and an optional width.

Original (max 2400px wide)

https://imgs.modscape.com/a7xK9mPq2w

Specific width

https://imgs.modscape.com/a7xK9mPq2w/400

Width must be between 1 and 2400 pixels. The aspect ratio is always preserved. If the requested width hasn't been generated before, it is created on the first request and cached for all future requests.

In HTML

<!-- Simple usage -->
<img src="https://imgs.modscape.com/a7xK9mPq2w/800" alt="My image">

<!-- Responsive with srcset -->
<img
  src="https://imgs.modscape.com/a7xK9mPq2w/800"
  srcset="
    https://imgs.modscape.com/a7xK9mPq2w/400 400w,
    https://imgs.modscape.com/a7xK9mPq2w/800 800w,
    https://imgs.modscape.com/a7xK9mPq2w/1200 1200w,
    https://imgs.modscape.com/a7xK9mPq2w/1600 1600w
  "
  sizes="(max-width: 600px) 400px, 800px"
  alt="My image"
>

<!-- As a CSS background -->
<div style="background-image: url('https://imgs.modscape.com/a7xK9mPq2w/1200')"></div>

Delete an Image

Removes the image and all generated sizes from disk.

curl -X DELETE https://imgs.modscape.com/a7xK9mPq2w \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{ "deleted": "a7xK9mPq2w" }

Error Responses

StatusBodyCause
400{ "error": "No file uploaded" }Upload request missing the file field
400{ "error": "Width must be between 1 and 2400" }Invalid width parameter
401{ "error": "Unauthorized" }Missing or invalid API key
404{ "error": "Image not found" }Image ID does not exist

Behavior Details

Typical Integration Pattern

When building an app with an admin panel that manages image uploads:

  1. Admin uploads an image via your app's backend.
  2. Your backend sends the image to POST /upload and receives the image ID.
  3. Store the image ID (e.g. a7xK9mPq2w) in your database alongside the related record.
  4. On the frontend, render images using the URL pattern: https://imgs.modscape.com/{id}/{width}.
  5. To delete, call DELETE /:id when the record is removed from your app.
// Example: save the image ID to your database
const uploadRes = await fetch('https://imgs.modscape.com/upload', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
  body: form
});
const { id } = await uploadRes.json();

// Save `id` to your database record
await db.query('UPDATE products SET image_id = $1 WHERE id = $2', [id, productId]);

// Later, on the frontend, render it at whatever size you need:
// <img src={`https://imgs.modscape.com/${product.image_id}/800`} />