Skip to content

Latest commit

 

History

History
196 lines (146 loc) · 5.72 KB

File metadata and controls

196 lines (146 loc) · 5.72 KB

API reference

All endpoints live under /api. Image upload endpoints accept multipart/form-data. Errors come back as JSON { error: { code, message, details? } }.


GET /api/health

Liveness probe. Always returns 200 if the process is up.

Response 200

{
  "ok": true,
  "version": "1.0.0",
  "env": "production",
  "timestamp": "2026-04-27T18:21:00.000Z"
}

GET /api/formats

Returns the supported input and output formats.

Response 200

{
  "input":  ["jpeg","jpg","png","webp","avif","svg","heic","heif","tiff","gif","bmp"],
  "output": ["jpeg","png","webp","avif"]
}

POST /api/compress

Compresses an image, optionally converting format, resizing, fitting to a target size, or applying edits.

Request — multipart/form-data

Field Type Required Description
file file yes Image to compress
outputFormat string no One of auto, jpeg, png, webp, avif. Default auto.
quality int 1–100 no Encoder quality. Default 80.
maxWidth int no Resize down so width ≤ this (preserves aspect).
maxHeight int no Resize down so height ≤ this (preserves aspect).
stripMetadata bool no Strip EXIF/IPTC/XMP. Default true.
targetMB float no Target output size in MB. When set, Feather binary-searches quality + resize until output ≤ target.
mode string no final (default) or preview.
progressive bool no Progressive JPEG.
effort int 0–9 no WebP/AVIF effort knob.
cropX, cropY, cropWidth, cropHeight int no Crop rectangle on the oriented source.
rotate float no Degrees, ±360.
flip, flop bool no Vertical / horizontal flip.
brightness float 0.1–3 no Brightness multiplier.
saturation float 0–3 no Saturation multiplier.
contrast float 0.1–3 no Contrast multiplier.
grayscale bool no Convert to grayscale.
blur float 0–10 no Gaussian blur sigma.
sharpen bool no Apply default sharpen.

Response 200 — image bytes

The body is the encoded image. Useful information rides on response headers:

Header Description
Content-Type image/<format>
Content-Disposition attachment; filename="<name>-compressed.<ext>"
X-Original-Bytes Input size in bytes
X-Output-Bytes Output size in bytes
X-Output-Quality Final quality used
X-Output-Width / X-Output-Height Output dimensions
X-Compression-Ratio original / output (e.g. 3.42)
X-Processing-Time-Ms End-to-end processing time
X-Target-Met true if targetMB was satisfied
X-Resized true if image was resized
X-Iterations Iterations used by target-fit search
X-RateLimit-Remaining Requests left in the current minute

Errors

Status Code Reason
400 INVALID_INPUT Missing file or invalid options
413 FILE_TOO_LARGE Upload exceeds MAX_UPLOAD_MB
415 UNSUPPORTED_FORMAT File extension/MIME not supported
422 INVALID_IMAGE Bytes are not a valid image
422 TOO_MANY_PIXELS Decoded dimensions exceed MAX_PIXELS
429 RATE_LIMIT_EXCEEDED Per-IP rate limit hit
504 TIMEOUT Processing exceeded REQUEST_TIMEOUT_MS
500 PROCESSING_FAILED Sharp/encoder error
500 INTERNAL_ERROR Unexpected server error

Examples

Basic:

curl -X POST http://localhost:3000/api/compress \
  -F "file=@photo.jpg" \
  -F "outputFormat=webp" \
  -F "quality=80" \
  --output out.webp

Target a 500 KB cap:

curl -X POST http://localhost:3000/api/compress \
  -F "file=@photo.jpg" \
  -F "targetMB=0.5" \
  --output out.webp

Resize + grayscale + AVIF:

curl -X POST http://localhost:3000/api/compress \
  -F "file=@photo.jpg" \
  -F "outputFormat=avif" \
  -F "maxWidth=1600" \
  -F "grayscale=true" \
  --output out.avif

POST /api/convert

Pure format conversion. Same parameters as /api/compress except:

  • outputFormat is required and may not be auto.
  • targetMB is ignored.

Example

curl -X POST http://localhost:3000/api/convert \
  -F "file=@photo.heic" \
  -F "outputFormat=jpeg" \
  -F "quality=85" \
  --output out.jpg

GET /api/models/modnet?variant=full|quantized

Internal endpoint used by the in-browser background-removal worker. Proxies and caches the MODNet ONNX model from a configurable upstream URL.

Query

Param Values Default Description
variant full | quantized full Which model to fetch.

Behavior

  1. Returns from in-process memory cache if warm.
  2. Otherwise reads from MODEL_CACHE_DIR (if set) and warms memory.
  3. Otherwise fetches from MODEL_FULL_URL / MODEL_QUANTIZED_URL, persists to disk, returns.

If HUGGINGFACE_TOKEN is set, the upstream fetch sends Authorization: Bearer <token>.

Response 200 — application/octet-stream

Cache-Control: public, max-age=31536000, immutable. The browser worker streams this into ONNX Runtime Web.

Errors

Status Code Reason
502 MODEL_FETCH_FAILED Upstream unreachable, returned non-2xx, or timed out (MODEL_FETCH_TIMEOUT_MS)

Rate limiting

Every /api/* endpoint that does work returns:

X-RateLimit-Limit:     60
X-RateLimit-Remaining: 59
X-RateLimit-Reset:     1714235520

When exceeded, the response is 429 Too Many Requests with Retry-After.

Configure with RATE_LIMIT_PER_MINUTE (default 60, set to 0 to disable).


CORS

Set CORS_ORIGINS to a comma-separated allowlist (or * to allow any). Preflight OPTIONS is handled by Next.js.