Browse Docs
On This Page

Endpoint: Compress

POST /compress — compress any supported file. The server detects the format from the file extension and routes to the appropriate compressor automatically.

Examples

cURL
# compress a JPG (file upload)
curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -F "file=@photo.jpg"

# compress a PNG
curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -F "file=@screenshot.png"

# compress a PDF
curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -F "file=@document.pdf"

# compress from URL (JSON body)
curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"inputUrl": "https://example.com/photo.jpg", "sourceFormat": "jpg"}'

# compress from URL (multipart field)
curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -F "inputUrl=https://example.com/photo.jpg" \
  -F "sourceFormat=jpg"
C#
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Fast-Api-Key", "fast_prod_your_key_here");

// File upload
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(File.ReadAllBytes("photo.jpg")), "file", "photo.jpg");

var response = await http.PostAsync("https://api.tools.fast/compress", form);
var job = await response.Content.ReadFromJsonAsync<JsonElement>();
var jobId = job.GetProperty("id").GetString();

// URL input (JSON body)
var urlResponse = await http.PostAsJsonAsync("https://api.tools.fast/compress",
    new { inputUrl = "https://example.com/photo.jpg", sourceFormat = "jpg" });
var urlJob = await urlResponse.Content.ReadFromJsonAsync<JsonElement>();
PowerShell
$headers = @{ "X-Fast-Api-Key" = "fast_prod_your_key_here" }

# compress a JPG (file upload)
Invoke-RestMethod -Method Post "https://api.tools.fast/compress" `
  -Headers $headers -Form @{ file = Get-Item "photo.jpg" }

# compress from URL (JSON body)
Invoke-RestMethod -Method Post "https://api.tools.fast/compress" `
  -Headers ($headers + @{ "Content-Type" = "application/json" }) `
  -Body '{"inputUrl": "https://example.com/photo.jpg", "sourceFormat": "jpg"}'

Method + path

  • POST /compress

The server resolves the compressor from the file extension. Supported formats: JPG, PNG, GIF, WebP, AVIF, HEIC, TIFF, BMP, PSD, 20+ RAW camera formats, PDF, DOCX, PPTX.

Auth

  • Required: X-Fast-Api-Key

Content type

Two input methods are supported:

MethodContent-TypeUse case
File uploadmultipart/form-dataUpload a file from disk
URL inputapplication/json or multipart/form-data with inputUrl fieldCompress a file from a URL

Form fields (multipart/form-data)

FieldRequiredTypeDescription
fileyes*fileThe file to compress
inputUrlyes*stringURL of a file to fetch and compress (mutually exclusive with file)
sourceFormatyes*stringSource format of the file at the URL (e.g. "jpg", "pdf"). Required when using inputUrl
optionsnoJSON stringResize and compression settings (see Options)
webhookUrlnostringHTTPS URL to receive a webhook POST on job completion
webhookSecretno (required with webhookUrl)stringShared secret for HMAC-SHA256 signature verification (16–256 chars)
webhookEventsnostringComma-separated event filter: succeeded, failed, or both (default: both)

* Exactly one of file or inputUrl must be provided. Sending both returns 400 url_fetch.mutually_exclusive.

Notes:

  • Exactly one file per request.
  • The file extension must match a supported format.
  • The options field is a JSON string — not a nested multipart section. See Options Reference for the full schema.

JSON body fields (application/json)

For URL-based input, send a JSON body instead of multipart:

FieldRequiredTypeDescription
inputUrlyesstringURL of the file to compress. Must be HTTPS. Supports presigned S3, GCS, and Azure Blob Storage URLs.
sourceFormatyesstringSource format of the file at the URL (e.g. "jpg", "pdf"). Required for URL input
optionsnoobjectCompressor-specific options (see Options)
outputUrlstringReserved for future use. Returns 400 if provided.
webhookUrlnostringHTTPS URL for job completion notifications
webhookSecretno (required with webhookUrl)stringShared secret for HMAC-SHA256 signature verification (16–256 chars)
webhookEventsnostringComma-separated event filter

JSON body example

{
  "inputUrl": "https://example.com/photo.jpg",
  "sourceFormat": "jpg",
  "options": {
    "quality": 80,
    "stripMetadata": true
  }
}

URL input notes

  • sourceFormat required — URL input requires sourceFormat so the server can validate format support and enforce per-compressor size limits before downloading. Omitting it returns url_fetch.missing_source_format.
  • Pre-download validation — The format is validated before fetching. Unsupported formats return compress.unsupported_format instantly (no download occurs).
  • Per-compressor size limits — The download cap uses the compressor's configured file size limit for your account, not a generic cap.
  • HTTPS required — HTTP URLs are rejected.
  • SSRF protection — Private IPs (10.x, 172.16-31.x, 192.168.x, 127.x), link-local (169.254.x), and IPv6 loopback are blocked.
  • Redirects — Up to 3 redirects are followed. Each hop is validated against the SSRF deny list.
  • Circuit breaker — Domains returning repeated errors are temporarily blocked to protect the service.
  • isRetryable — URL fetch errors include an isRetryable boolean indicating whether the request can be retried.

Response

202 Accepted with job details.

Example response

{
  "id": "019c56454f8b755996c45a4874a1f3f6",
  "status": "Queued",
  "fileName": "photo",
  "format": "jpg",
  "...": "see JobAcceptedResponse model for all fields"
}

Full workflow

cURL
API_KEY="fast_prod_your_key_here"

# 1) submit
JOB_ID=$(curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -F "file=@photo.jpg" | jq -r '.id')

# 2) poll
while true; do
  STATUS=$(curl -sS "https://api.tools.fast/compress/job/${JOB_ID}" \
    -H "X-Fast-Api-Key: $API_KEY" | jq -r '.status')
  [ "${STATUS}" = "Succeeded" ] && break
  [ "${STATUS}" = "Failed" ] || [ "${STATUS}" = "Canceled" ] && exit 1
  sleep 1
done

# 3) download
curl -sS "https://api.tools.fast/compress/job/${JOB_ID}/download" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -o "photo-compressed.jpg"
C#
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Fast-Api-Key", "fast_prod_your_key_here");

// 1) submit
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(File.ReadAllBytes("photo.jpg")), "file", "photo.jpg");
var submit = await http.PostAsync("https://api.tools.fast/compress", form);
var job = await submit.Content.ReadFromJsonAsync<JsonElement>();
var jobId = job.GetProperty("id").GetString();

// 2) poll
string status;
do
{
    await Task.Delay(1000);
    var poll = await http.GetFromJsonAsync<JsonElement>(
        $"https://api.tools.fast/compress/job/{jobId}");
    status = poll.GetProperty("status").GetString()!;
} while (status is "Queued" or "Running");

// 3) download
var output = await http.GetByteArrayAsync(
    $"https://api.tools.fast/compress/job/{jobId}/download");
File.WriteAllBytes("photo-compressed.jpg", output);
PowerShell
$headers = @{ "X-Fast-Api-Key" = "fast_prod_your_key_here" }

# 1) submit
$job = Invoke-RestMethod -Method Post "https://api.tools.fast/compress" `
  -Headers $headers `
  -Form @{ file = Get-Item "photo.jpg" }

# 2) poll
do {
  $status = (Invoke-RestMethod "https://api.tools.fast/compress/job/$($job.id)" `
    -Headers $headers).status
  if ($status -in "Failed", "Canceled") { throw "Job $($job.id) $status" }
  Start-Sleep -Seconds 1
} while ($status -ne "Succeeded")

# 3) download
Invoke-RestMethod "https://api.tools.fast/compress/job/$($job.id)/download" `
  -Headers $headers -OutFile "photo-compressed.jpg"

Compress from URL (full workflow)

cURL
API_KEY="fast_prod_your_key_here"

# 1) submit from URL
JOB_ID=$(curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"inputUrl": "https://example.com/photo.jpg", "sourceFormat": "jpg"}' | jq -r '.id')

# 2) poll
while true; do
  STATUS=$(curl -sS "https://api.tools.fast/compress/job/${JOB_ID}" \
    -H "X-Fast-Api-Key: $API_KEY" | jq -r '.status')
  [ "${STATUS}" = "Succeeded" ] && break
  [ "${STATUS}" = "Failed" ] || [ "${STATUS}" = "Canceled" ] && exit 1
  sleep 1
done

# 3) download
curl -sS "https://api.tools.fast/compress/job/${JOB_ID}/download" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -o "photo-compressed.jpg"
C#
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Fast-Api-Key", "fast_prod_your_key_here");

// 1) submit from URL
var urlResponse = await http.PostAsJsonAsync("https://api.tools.fast/compress",
    new { inputUrl = "https://example.com/photo.jpg", sourceFormat = "jpg" });
var job = await urlResponse.Content.ReadFromJsonAsync<JsonElement>();
var jobId = job.GetProperty("id").GetString();

// 2) poll
string status;
do
{
    await Task.Delay(1000);
    var poll = await http.GetFromJsonAsync<JsonElement>(
        $"https://api.tools.fast/compress/job/{jobId}");
    status = poll.GetProperty("status").GetString()!;
} while (status is "Queued" or "Running");

// 3) download
var output = await http.GetByteArrayAsync(
    $"https://api.tools.fast/compress/job/{jobId}/download");
File.WriteAllBytes("photo-compressed.jpg", output);

With webhook notification

cURL
# Compress with webhook — no polling needed
curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -F "file=@photo.jpg" \
  -F "webhookUrl=https://example.com/webhooks/fast" \
  -F "webhookSecret=whsec_your_secret_here"
C#
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(File.ReadAllBytes("photo.jpg")), "file", "photo.jpg");
form.Add(new StringContent("https://example.com/webhooks/fast"), "webhookUrl");
form.Add(new StringContent("whsec_your_secret_here"), "webhookSecret");

var response = await http.PostAsync("https://api.tools.fast/compress", form);
// No polling needed — your webhook endpoint will be called on completion
PowerShell
# Compress with webhook — no polling needed
Invoke-RestMethod -Method Post "https://api.tools.fast/compress" `
  -Headers $headers `
  -Form @{
    file = Get-Item "photo.jpg"
    webhookUrl = "https://example.com/webhooks/fast"
    webhookSecret = "whsec_your_secret_here"
  }

See Webhooks for payload schema, signature verification, and retry policy.

Unsupported format error

If the file extension isn't supported, you'll get a 400 with the list of supported formats:

{
  "error": "compress.unsupported_format",
  "detail": "Unsupported file format: '.mp3'.",
  "supportedFormats": [".avif", ".bmp", ".docx", ".gif", ".jpg", "..."]
}

Errors

See Errors for the full error reference with JSON examples.

StatusCodesCause
400request.invalid_content_type, request.no_files, request.empty_file, request.invalid_extension, request.multiple_files, compress.unsupported_format, compress.invalid_webhook, url_fetch.missing_source_format, url_fetch.invalid_url, url_fetch.invalid_scheme, url_fetch.private_ip, url_fetch.mutually_exclusive, url_fetch.output_url_reserved, url_fetch.http_error, url_fetch.dns_failure, url_fetch.timeout, url_fetch.too_large, url_fetch.redirect_loop, url_fetch.redirect_denied, url_fetch.domain_circuit_open, url_fetch.url_expired, url_fetch.no_filename, url_fetch.invalid_contentBad request payload
401api_key.invalid_or_ip_not_allowedInvalid API key or IP not allowlisted
402entitlements.insufficient_creditsNot enough credits
403url_fetch.guest_not_allowedURL input requires a signed-in account
413request.file_too_largeFile exceeds size limit
429rate_limited, queue.limit_exceeded, url_fetch.rate_limitedThrottled
Copied.