Back to home

API Documentation

Integrate image compression into your applications with our REST API.

Quick Start

1

Get your API Key

Sign up for Pro to get API access

2

Make your first request

Include your API key in the X-API-Key header

curl -X POST https://api.squish.dev/api/v1/compress/single \
  -H "X-API-Key: sq_live_your_key_here" \
  -F "image=@photo.jpg"
3

Get compressed image

Response includes base64-encoded compressed image and savings stats

Authentication

All API requests require authentication via the X-API-Key header.

X-API-Key: sq_live_your_api_key_here

Keep your API key secret! Don't expose it in client-side code or public repositories.

Endpoints

POST/api/v1/compress/single

Compress a single image

Auth: API Key

Parameters

NameTypeRequiredDescription
imagefileYesImage file (JPEG, PNG, WebP, AVIF)
qualitynumberNoCompression quality 1-100 (default: 80)
formatstringNoOutput format: jpeg, png, webp, avif
maxWidthnumberNoMaximum width in pixels
maxHeightnumberNoMaximum height in pixels

Example Request

curl -X POST https://api.squish.dev/api/v1/compress/single \
  -H "X-API-Key: sq_live_your_key_here" \
  -F "image=@photo.jpg" \
  -F "quality=80" \
  -F "format=webp"

Response

{
  "success": true,
  "original": { "size": 2457600 },
  "compressed": { "size": 312000 },
  "savings": "87%",
  "image": "base64_encoded_image..."
}
POST/api/v1/compress/bulk

Compress multiple images (returns ZIP)

Auth: API Key (Pro)

Parameters

NameTypeRequiredDescription
imagesfilesYesMultiple image files (max 20)
qualitynumberNoCompression quality 1-100
formatstringNoOutput format: jpeg, png, webp, avif

Example Request

curl -X POST https://api.squish.dev/api/v1/compress/bulk \
  -H "X-API-Key: sq_live_your_key_here" \
  -F "images=@photo1.jpg" \
  -F "images=@photo2.jpg" \
  -F "images=@photo3.jpg" \
  -F "quality=75"

Response

{
  "success": true,
  "count": 5,
  "zip": "base64_encoded_zip..."
}
GET/api/v1/usage

Get current usage statistics

Auth: API Key or JWT

Example Request

curl https://api.squish.dev/api/v1/usage \
  -H "X-API-Key: sq_live_your_key_here"

Response

{
  "tier": "pro",
  "usage": {
    "images": 150,
    "bytesSaved": 52428800
  },
  "limits": {
    "maxImages": 2000,
    "maxFileSize": 26214400
  },
  "remaining": 1850
}

Which Image Format Should I Use?

Squish supports JPEG, PNG, WebP, and AVIF. Here’s a quick cheat sheet:

Use this formatBest forNotes
webpMost photos & marketing imagesGreat balance of size and quality. Widely supported.
avifPerformance‑critical pages, hero imagesSmallest files; use with fallback if you need legacy support.
jpegOlder browsers, email clientsSafe choice when you can’t rely on modern formats.
pngLogos, UI icons, graphics with transparencyLossless; keep when you need pixel‑perfect edges.

Want a deeper dive into formats? Read our blog post “Complete Guide to Image Compression”.

Rate Limits

TierImages/MonthMax File SizeCDN RetentionBulk API
Free505 MB24 hoursNo
Pro2,00025 MB7 daysYes
Team10,00050 MB30 daysYes
Enterprise100,000100 MBUnlimitedYes

Integration Examples

React: Upload & Compress an Image

This example shows how to call the Squish API from a React component using a file input and fetch.

import React, { useState } from 'react';

function SquishUploader() {
  const [saving, setSaving] = useState(false);
  const [result, setResult] = useState(null);

  const handleChange = async (event) => {
    const file = event.target.files?.[0];
    if (!file) return;

    const formData = new FormData();
    formData.append('image', file);
    formData.append('quality', '80');
    formData.append('format', 'webp');

    setSaving(true);
    try {
      const response = await fetch('https://api.squish.dev/api/v1/compress/single', {
        method: 'POST',
        headers: {
          'X-API-Key': 'sq_live_your_key_here',
        },
        body: formData,
      });

      const data = await response.json();
      setResult(data);
    } finally {
      setSaving(false);
    }
  };

  return (
    <div>
      <input type="file" accept="image/*" onChange={handleChange} />
      {saving && <p>Compressing...</p>}
      {result && (
        <div>
          <p>Savings: {result.savings}</p>
          {/* If you requested base64 output */}
          {result.image && (
            <img
              src={`data:image/webp;base64,${result.image}`}
              alt="Compressed"
            />
          )}
          {/* If you requested URL output (output=url) */}
          {result.url && (
            <img
              src={result.url}
              alt="Compressed from CDN"
            />
          )}
        </div>
      )}
    </div>
  );
}

export default SquishUploader;

Node.js / Express: Compress Before Uploading to Your App

Use this pattern in your backend to compress images via Squish before storing them in your own storage or database.

import express from 'express';
import multer from 'multer';
import axios from 'axios';
import FormData from 'form-data';

const app = express();
const upload = multer({ storage: multer.memoryStorage() });

app.post('/upload', upload.single('image'), async (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No image provided' });
  }

  const form = new FormData();
  form.append('image', req.file.buffer, req.file.originalname);
  form.append('quality', '80');
  form.append('format', 'webp');
  form.append('output', 'url'); // get CDN URL instead of base64

  try {
    const response = await axios.post(
      'https://api.squish.dev/api/v1/compress/single',
      form,
      {
        headers: {
          'X-API-Key': process.env.SQUISH_API_KEY!,
          ...form.getHeaders(),
        },
      }
    );

    const data = response.data;

    // Store data.url (CDN URL) in your database, associate with user, etc.
    // await saveImageForUser(req.user.id, data.url);

    return res.json({
      success: true,
      cdnUrl: data.url,
      downloadUrl: data.downloadUrl,
      savings: data.savings,
    });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ error: 'Failed to compress image' });
  }
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});