Optimize
API v1 — REST

API Documentation

Integrate automatic image optimization into any website or application. Auto-resize images on user upload, convert formats, and compress — in any language.

Quick Start — 3 Steps
1

Create a free account

Sign up in 30 seconds. No credit card required. Get instant API access.

2

Get your API key

Find it in your dashboard. Keep it secret — it's your authentication token.

3

Make your first API call

Use any language below. Start with cURL to test, then integrate into your app.

Endpoint
POST
/api/v1/convert
multipart/form-data

Base URL: https://optimize.robinswebdesign.com

Authentication

All API requests require an API key passed via the x-api-key header.

HeaderRequiredDescription
x-api-key
Required
Your API key from the dashboard
Parameters
ParameterTypeRequiredDescriptionDefault
imageFile
Yes
The image file to optimize-
formatstring
No
Output format: webp, png, jpeg, avifwebp
qualitynumber
No
Compression quality 1-10080
widthnumber
No
Output width in pixelsauto
heightnumber
No
Output height in pixelsauto
maintainAspectRatioboolean
No
Preserve aspect ratio when resizingtrue
removeMetadataboolean
No
Strip EXIF and metadatafalse
inlineboolean
No
Return image directly (not JSON)false
Response Format

Successful response (when inline=false):

{
  "success": true,
  "id": "abc123-def456",
  "originalName": "photo.png",
  "originalSize": 5242880,
  "optimizedSize": 870400,
  "compressionPercent": "83.4%",
  "width": 1200,
  "height": 800,
  "originalFormat": "png",
  "optimizedFormat": "webp",
  "downloadUrl": "/api/download?id=abc123-def456",
  "usage": {
    "used": 1,
    "limit": 10,
    "remaining": 9
  }
}
Error Codes
CodeHTTP StatusMeaning
INVALID_API_KEY
401
API key is missing or invalid
DAILY_LIMIT_REACHED
429
Daily conversion limit exceeded
FILE_TOO_LARGE
400
File exceeds your tier's size limit
UNSUPPORTED_FORMAT
400
Image format not supported
PROCESSING_ERROR
500
Image processing failed

Code Examples in Every Language

Ready-to-use code snippets for every popular backend language. Copy and paste into your project.

cURL
curl -X POST https://optimize.robinswebdesign.com/api/v1/convert \
  -H "x-api-key: YOUR_API_KEY" \
  -F "[email protected]" \
  -F "format=webp" \
  -F "quality=80" \
  -F "width=1200"
Node.js
import { createReadStream } from 'fs'
import FormData from 'form-data'

async function optimizeImage(imagePath) {
  const form = new FormData()
  form.append('image', createReadStream(imagePath))
  form.append('format', 'webp')
  form.append('width', '1200')

  const res = await fetch(
    'https://optimize.robinswebdesign.com/api/v1/convert',
    {
      method: 'POST',
      headers: { 'x-api-key': process.env.IMG_API_KEY },
      body: form,
    }
  )
  return res.json()
}
Python
import requests

def optimize_image(image_path):
    url = "https://optimize.robinswebdesign.com/api/v1/convert"
    headers = {"x-api-key": "YOUR_API_KEY"}
    
    with open(image_path, "rb") as f:
        files = {"image": f}
        data = {"format": "webp", "quality": 80, "width": 1200}
        res = requests.post(url, headers=headers, files=files, data=data)
    
    return res.json()

# Auto-resize user uploads in Django/Flask
result = optimize_image("user_upload.png")
print(f"Saved: {result['compressionPercent']}")
PHP
<?php
function optimizeImage($imagePath) {
    $url = "https://optimize.robinswebdesign.com/api/v1/convert";
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "x-api-key: YOUR_API_KEY"
    ]);
    
    $postFields = [
        'image' => new CURLFile($imagePath),
        'format' => 'webp',
        'quality' => '80',
        'width' => '1200'
    ];
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
    
    $result = curl_exec($ch);
    curl_close($ch);
    
    return json_decode($result, true);
}

// WordPress plugin integration
add_action('wp_handle_upload', function($data) {
    $optimized = optimizeImage($data['file']);
    // Save optimized version
    return $data;
});
Next.js Server Action
'use server'

export async function optimizeUserImage(formData: FormData) {
  formData.append('format', 'webp')
  formData.append('quality', '80')
  formData.append('width', '1200')

  const res = await fetch(
    'https://optimize.robinswebdesign.com/api/v1/convert',
    {
      method: 'POST',
      headers: { 'x-api-key': process.env.IMG_API_KEY },
      body: formData,
    }
  )
  
  const result = await res.json()
  
  // Download and save optimized image
  const imgRes = await fetch(result.downloadUrl)
  const buffer = await imgRes.arrayBuffer()
  // Save to your storage (S3, Vercel Blob, etc.)
  
  return result
}
WordPress (PHP)
<?php
// Add to functions.php - auto-optimize on upload
add_filter('wp_generate_attachment_metadata', function($metadata, $attachment_id) {
    $file = get_attached_file($attachment_id);
    
    $response = wp_remote_post(
        'https://optimize.robinswebdesign.com/api/v1/convert',
        [
            'headers' => ['x-api-key' => 'YOUR_API_KEY'],
            'body' => [
                'image' => new CURLFile($file),
                'format' => 'webp',
                'width' => '1920',
            ],
        ]
    );
    
    if (!is_wp_error($response)) {
        $data = json_decode($response['body'], true);
        // Download optimized version
        $optimized = file_get_contents(
            'https://optimize.robinswebdesign.com' . $data['downloadUrl']
        );
        $webp_path = preg_replace('/.[^.]+$/', '.webp', $file);
        file_put_contents($webp_path, $optimized);
    }
    
    return $metadata;
}, 10, 2);
Ruby
require 'net/http'
require 'uri'

def optimize_image(image_path)
  uri = URI('https://optimize.robinswebdesign.com/api/v1/convert')
  
  request = Net::HTTP::Post.new(uri)
  request['x-api-key'] = 'YOUR_API_KEY'
  
  form_data = [
    ['image', File.open(image_path)],
    ['format', 'webp'],
    ['quality', '80'],
    ['width', '1200']
  ]
  request.set_form(form_data, 'multipart/form-data')
  
  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
    http.request(request)
  end
  
  JSON.parse(response.body)
end

# Rails callback for Active Storage
class ImageOptimizer
  def self.after_upload(blob)
    result = optimize_image(blob.service.path_for(blob.key))
    Rails.logger.info "Saved: #{result['compressionPercent']}"
  end
end
Go
package main

import (
  "bytes"
  "encoding/json"
  "io"
  "mime/multipart"
  "net/http"
  "os"
)

func optimizeImage(imagePath string) (map[string]interface{}, error) {
  var buf bytes.Buffer
  writer := multipart.NewWriter(&buf)
  
  file, _ := os.Open(imagePath)
  defer file.Close()
  
  part, _ := writer.CreateFormFile("image", "photo.png")
  io.Copy(part, file)
  writer.WriteField("format", "webp")
  writer.WriteField("quality", "80")
  writer.WriteField("width", "1200")
  writer.Close()
  
  req, _ := http.NewRequest("POST",
    "https://optimize.robinswebdesign.com/api/v1/convert",
    &buf)
  req.Header.Set("Content-Type", writer.FormDataContentType())
  req.Header.Set("x-api-key", "YOUR_API_KEY")
  
  client := &http.Client{}
  resp, _ := client.Do(req)
  defer resp.Body.Close()
  
  var result map[string]interface{}
  json.NewDecoder(resp.Body).Decode(&result)
  return result, nil
}
Rate Limits & Plans
Free

10

conversions / day

300 / month

Max file: 5MB

1 concurrent job

$0

Pro

500

conversions / day

15,000 / month

Max file: 20MB

5 concurrent jobs

Coming Soon

Enterprise

5,000

conversions / day

150,000 / month

Max file: 100MB

20 concurrent jobs

Coming Soon

Best Practices

Use the <picture> element for maximum compatibility

<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.avif" type="image/avif">
  <img src="image.jpg" alt="Fallback">
</picture>

Auto-resize on blog post upload (Next.js)

In your Next.js API route or Server Action, when a user uploads a blog image, forward it to our API with width=1200 and format=webp. Save the optimized version to your storage. Your blog images will always be perfectly sized.

Cache optimized images on your CDN

Our download URLs support Cache-Control headers. Set up your CDN to cache optimized images for maximum performance. Files are available for 30 minutes.