REST API reference

Compress images from your own code. Authenticate with an API key, post a file, poll the job, download the result from a signed URL.

Last updated

The API is available on every paid plan. It runs the same compression core as the browser tool, but bulk work goes onto a queue and is handled by a separate worker process, so a large batch never blocks or times out on the request thread.

The base URL in these examples is https://imagecompressor.tools.

Authentication

Create a key in the dashboard under API keys. The key is shown exactly once, at creation. Only a SHA-256 hash of it is stored, so if you lose it, nobody can recover it for you and you will need to mint a new one.

Send it as a bearer token:

Authorization: Bearer sk_your_key_here

An x-api-key: sk_your_key_here header works too. A revoked key returns 401.

Compress an image

POST /api/compress
Content-Type: multipart/form-data
Field Required Description
file yes The image to compress.
format no One of webp, avif, jpeg, png. Defaults to keeping the input format, falling back to webp.
quality no 1 to 100. Defaults to 80.
curl -X POST https://imagecompressor.tools/api/compress \
  -H "Authorization: Bearer $API_KEY" \
  -F "file=@photo.jpg" \
  -F "format=webp" \
  -F "quality=80"

The response is immediate, before any pixels have been touched:

{
  "jobId": "cmr8kuk2c0000neq9hd3fzs47",
  "status": "PENDING"
}

The plan check happens before the upload and before the job is enqueued, so an over-limit request costs you nothing and is rejected right away. A file over your plan's per-image size limit returns 413. Exhausting your monthly allowance returns 429.

Poll the job

GET /api/job/{jobId}
curl https://imagecompressor.tools/api/job/$JOB_ID \
  -H "Authorization: Bearer $API_KEY"
{
  "jobId": "cmr8kuk2c0000neq9hd3fzs47",
  "status": "COMPLETED",
  "ready": true,
  "downloadUrl": "/api/download/cmr8kuk2c0000neq9hd3fzs47",
  "outputMeta": {
    "format": "webp",
    "inputBytes": 1016832,
    "outputBytes": 109978,
    "bytesSaved": 906854,
    "percentSaved": 88.9,
    "width": 2000,
    "height": 1500
  }
}

status moves PENDING, PROCESSING, then COMPLETED or FAILED. Poll every second or so. Jobs are scoped to the key's owner: asking for someone else's job id returns 404, not 403, because you should not be able to learn that it exists.

Download the result

GET /api/download/{jobId}

This does not stream the file. It mints a signed URL that is valid for 15 minutes and redirects to it with a 302, so the bytes come straight from object storage. Follow redirects:

curl -L -o optimized.webp https://imagecompressor.tools/api/download/$JOB_ID \
  -H "Authorization: Bearer $API_KEY"

Results are deleted 24 hours after they are created. Downloading after that returns 410 Gone. Download promptly, or re-submit.

A complete example

#!/usr/bin/env bash
set -euo pipefail

JOB=$(curl -sS -X POST https://imagecompressor.tools/api/compress \
  -H "Authorization: Bearer $API_KEY" \
  -F "file=@photo.jpg" -F "format=webp" | jq -r .jobId)

until [ "$(curl -sS "https://imagecompressor.tools/api/job/$JOB" \
  -H "Authorization: Bearer $API_KEY" | jq -r .ready)" = "true" ]; do
  sleep 1
done

curl -sSL -o optimized.webp "https://imagecompressor.tools/api/download/$JOB" \
  -H "Authorization: Bearer $API_KEY"

Metering

One image is one unit. The API has no browser session, so every call to /api/compress uploads one image and consumes one unit. The browser tool behaves differently: there, re-compressing the same image at another quality or format within a session is free, because you have already paid for that image.

Pricing is a flat monthly fee per plan. There is no per-image charge on top, at any volume.

Errors

Status Meaning
400 The request was not multipart, or file was missing.
401 No key, an unknown key, or a revoked key.
404 No such job, or it belongs to someone else.
409 The job is not finished yet.
410 The result has passed its retention window and been deleted.
413 The file is over your plan's per-image size limit.
422 The upload could not be decoded as an image.
429 You have used your monthly allowance.

Errors are always JSON with an error field carrying a sentence you can show a user.