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.