Files
IOPaint/docs/RESTFUL_API_DOCUMENTATION.md
let5sne b6ac3f022a 📁 重组文档目录结构
变更:
- 创建 docs/ 目录统一管理所有文档
- 移动所有 API 文档到 docs/ 目录
  - API_DOCS_INDEX.md
  - RESTFUL_API_DOCUMENTATION.md
  - API_SERVICE_README.md
  - API_CLIENT_EXAMPLES.md
  - API_SERVICE_GUIDE.md
  - BRANCH_README.md
  - openapi.yaml
  - IOPaint_API.postman_collection.json
  - UPGRADE_NOTES.md

- 更新所有文档间的引用路径
- 更新 README.md 中的文档链接
- 创建 docs/README.md 作为文档入口

优势:
 清晰的目录结构
 文档集中管理
 易于查找和维护
 符合项目规范

🔧 Generated with Claude Code
2025-11-28 18:04:26 +00:00

22 KiB

IOPaint REST API Documentation

Official REST API documentation for IOPaint Watermark Removal Service.

Version: v1 Base URL: https://api.iopaint.com (production) or http://localhost:8080 (development) Protocol: HTTPS (production), HTTP (development)


Table of Contents

  1. Introduction
  2. Authentication
  3. API Endpoints
  4. Models
  5. Error Handling
  6. Rate Limiting
  7. Best Practices
  8. SDKs & Libraries
  9. Changelog

Introduction

The IOPaint API provides AI-powered watermark removal capabilities through a simple REST API. Built on the LaMa (Large Mask Inpainting) model, it offers fast and high-quality image restoration.

Key Features

  • Fast Processing: 1-2 seconds for 1024x1024 images
  • High Quality: State-of-the-art AI model
  • Simple Integration: Standard REST API with multipart/form-data
  • Flexible: Optional mask support for precise control
  • Scalable: From hobby projects to enterprise deployments

API Capabilities

Feature Status Description
Watermark Removal Available Remove watermarks from images
Auto Detection Coming Soon Automatic watermark detection
Batch Processing Coming Soon Process multiple images at once
Webhook Callbacks Coming Soon Async processing with callbacks

Authentication

The IOPaint API uses API keys for authentication. All requests must include your API key in the request header.

Obtaining an API Key

  1. Sign up at https://iopaint.com/signup
  2. Navigate to your Dashboard
  3. Generate a new API key
  4. Store it securely (keys cannot be recovered)

Using Your API Key

Include your API key in the X-API-Key header with every request:

X-API-Key: your_api_key_here

Security Best Practices

  • ⚠️ Never expose your API key in client-side code
  • Store keys in environment variables
  • Rotate keys periodically
  • Use different keys for development and production
  • Revoke compromised keys immediately

Example

# ✅ Correct
curl https://api.iopaint.com/api/v1/health \
  -H "X-API-Key: $IOPAINT_API_KEY"

# ❌ Incorrect (hardcoded key)
curl https://api.iopaint.com/api/v1/health \
  -H "X-API-Key: sk_live_1234567890abcdef"

API Endpoints

Base URL

Production: https://api.iopaint.com
Development: http://localhost:8080

Endpoint Overview

Endpoint Method Description
/api/v1/remove-watermark POST Remove watermark from image
/api/v1/health GET Service health check
/api/v1/stats GET Account usage statistics

1. Remove Watermark

Remove watermarks or unwanted objects from images using AI.

Endpoint

POST /api/v1/remove-watermark

Authentication

Required. Include X-API-Key header.

Request Headers

Header Type Required Description
X-API-Key string Yes Your API key
Content-Type string Yes Must be multipart/form-data

Request Body

Submit as multipart/form-data:

Field Type Required Max Size Description
image file Yes 10 MB Image to process (JPEG, PNG, WebP)
mask file No 10 MB Optional mask (white = remove, black = keep)

Image Requirements

  • Formats: JPEG, PNG, WebP
  • Max Dimension: 4096px (width or height)
  • Max File Size: 10 MB
  • Color Mode: RGB (grayscale will be converted)

Mask Requirements

  • Format: PNG (8-bit grayscale or RGB)
  • Dimension: Must match image size (auto-resized if different)
  • White (255): Areas to remove/inpaint
  • Black (0): Areas to preserve
  • Gray: Partial inpainting (blend)

Response

Success (200 OK)

Returns the processed image as image/png.

Response Headers:

Header Type Description
Content-Type string image/png
X-Processing-Time float Processing time in seconds
X-Image-Size string Original image dimensions (e.g., "1024x768")

Examples

cURL

# Basic usage (no mask)
curl -X POST https://api.iopaint.com/api/v1/remove-watermark \
  -H "X-API-Key: $IOPAINT_API_KEY" \
  -F "image=@/path/to/image.jpg" \
  -o result.png

# With mask
curl -X POST https://api.iopaint.com/api/v1/remove-watermark \
  -H "X-API-Key: $IOPAINT_API_KEY" \
  -F "image=@/path/to/image.jpg" \
  -F "mask=@/path/to/mask.png" \
  -o result.png

# Verbose output
curl -X POST https://api.iopaint.com/api/v1/remove-watermark \
  -H "X-API-Key: $IOPAINT_API_KEY" \
  -F "image=@image.jpg" \
  -v \
  -o result.png

Python

import requests

url = "https://api.iopaint.com/api/v1/remove-watermark"
headers = {"X-API-Key": "your_api_key_here"}

# Basic usage
with open("image.jpg", "rb") as f:
    files = {"image": f}
    response = requests.post(url, headers=headers, files=files)

if response.status_code == 200:
    with open("result.png", "wb") as f:
        f.write(response.content)
    print(f"✓ Success! Processing time: {response.headers['X-Processing-Time']}s")
else:
    print(f"✗ Error {response.status_code}: {response.json()}")

JavaScript/Node.js

const FormData = require('form-data');
const fs = require('fs');
const axios = require('axios');

const form = new FormData();
form.append('image', fs.createReadStream('image.jpg'));

axios.post('https://api.iopaint.com/api/v1/remove-watermark', form, {
    headers: {
        'X-API-Key': process.env.IOPAINT_API_KEY,
        ...form.getHeaders()
    },
    responseType: 'arraybuffer'
})
.then(response => {
    fs.writeFileSync('result.png', response.data);
    console.log('✓ Success!');
})
.catch(error => {
    console.error('✗ Error:', error.response?.status, error.response?.data);
});

PHP

<?php
$ch = curl_init('https://api.iopaint.com/api/v1/remove-watermark');

curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'image' => new CURLFile('/path/to/image.jpg')
]);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'X-API-Key: your_api_key_here'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode == 200) {
    file_put_contents('result.png', $result);
    echo "✓ Success!\n";
} else {
    echo "✗ Error: $httpCode\n";
}
?>

Go

package main

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

func main() {
    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    // Add image file
    file, _ := os.Open("image.jpg")
    defer file.Close()
    part, _ := writer.CreateFormFile("image", "image.jpg")
    io.Copy(part, file)
    writer.Close()

    // Create request
    req, _ := http.NewRequest("POST", "https://api.iopaint.com/api/v1/remove-watermark", body)
    req.Header.Set("X-API-Key", os.Getenv("IOPAINT_API_KEY"))
    req.Header.Set("Content-Type", writer.FormDataContentType())

    // Send request
    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()

    // Save result
    out, _ := os.Create("result.png")
    defer out.Close()
    io.Copy(out, resp.Body)
}

2. Health Check

Check the API service status and availability.

Endpoint

GET /api/v1/health

Authentication

Not required.

Response

Success (200 OK)

{
  "status": "healthy",
  "model": "lama",
  "device": "cuda",
  "gpu_available": true
}

Response Fields:

Field Type Description
status string Service status: healthy or unhealthy
model string Current AI model name
device string Compute device: cuda (GPU) or cpu
gpu_available boolean GPU availability

Example

curl https://api.iopaint.com/api/v1/health
import requests

response = requests.get("https://api.iopaint.com/api/v1/health")
print(response.json())
# Output: {'status': 'healthy', 'model': 'lama', 'device': 'cuda', 'gpu_available': True}

3. Usage Statistics

Retrieve your account usage statistics.

Endpoint

GET /api/v1/stats

Authentication

Required. Include X-API-Key header.

Response

Success (200 OK)

{
  "total": 1250,
  "success": 1230,
  "failed": 20,
  "total_processing_time": 1845.5,
  "avg_processing_time": 1.5
}

Response Fields:

Field Type Description
total integer Total requests made
success integer Successful requests
failed integer Failed requests
total_processing_time float Cumulative processing time (seconds)
avg_processing_time float Average processing time (seconds)

Example

curl https://api.iopaint.com/api/v1/stats \
  -H "X-API-Key: $IOPAINT_API_KEY"
import requests

headers = {"X-API-Key": "your_api_key_here"}
response = requests.get("https://api.iopaint.com/api/v1/stats", headers=headers)
stats = response.json()

print(f"Total requests: {stats['total']}")
print(f"Success rate: {stats['success'] / stats['total'] * 100:.2f}%")
print(f"Average time: {stats['avg_processing_time']:.2f}s")

Models

LaMa (Current)

Large Mask Inpainting - Fast and efficient inpainting model.

Property Value
Name lama
Speed (1-2s for 1024x1024)
Quality
VRAM ~1GB
Best For Watermark removal, object removal

Future Models (Coming Soon)

Model Speed Quality VRAM Use Case
SD Inpainting ~4GB Creative editing
SDXL Inpainting ~8GB Professional work

Error Handling

Error Response Format

All errors return a JSON object with the following structure:

{
  "error": "ErrorType",
  "detail": "Human-readable error message",
  "status_code": 400
}

HTTP Status Codes

Code Status Description
200 OK Request successful
400 Bad Request Invalid request parameters
401 Unauthorized Missing or invalid API key
413 Payload Too Large File exceeds size limit
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server-side error
503 Service Unavailable Service temporarily unavailable

Error Types

401 Unauthorized

Missing API Key:

{
  "error": "Unauthorized",
  "detail": "Missing API Key. Please provide X-API-Key header.",
  "status_code": 401
}

Invalid API Key:

{
  "error": "Unauthorized",
  "detail": "Invalid API Key",
  "status_code": 401
}

400 Bad Request

Invalid Image Format:

{
  "error": "Bad Request",
  "detail": "Invalid image format: cannot identify image file",
  "status_code": 400
}

Image Too Large:

{
  "error": "Bad Request",
  "detail": "Image too large. Max dimension: 4096px",
  "status_code": 400
}

File Too Large:

{
  "error": "Bad Request",
  "detail": "Image too large. Max size: 10MB",
  "status_code": 400
}

429 Rate Limit Exceeded

{
  "error": "Too Many Requests",
  "detail": "Rate limit exceeded. Please try again later.",
  "status_code": 429
}

Headers:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1672531200

500 Internal Server Error

{
  "error": "Internal Server Error",
  "detail": "Processing failed: CUDA out of memory",
  "status_code": 500
}

Error Handling Best Practices

import requests
import time

def remove_watermark_with_retry(image_path, max_retries=3):
    """Remove watermark with exponential backoff retry"""
    url = "https://api.iopaint.com/api/v1/remove-watermark"
    headers = {"X-API-Key": os.getenv("IOPAINT_API_KEY")}

    for attempt in range(max_retries):
        try:
            with open(image_path, "rb") as f:
                response = requests.post(
                    url,
                    headers=headers,
                    files={"image": f},
                    timeout=120
                )

            if response.status_code == 200:
                return response.content

            elif response.status_code == 429:
                # Rate limit - exponential backoff
                wait_time = 2 ** attempt
                print(f"Rate limited. Waiting {wait_time}s...")
                time.sleep(wait_time)
                continue

            elif response.status_code in [500, 503]:
                # Server error - retry
                if attempt < max_retries - 1:
                    time.sleep(2 ** attempt)
                    continue
                else:
                    raise Exception(f"Server error: {response.json()}")

            else:
                # Client error - don't retry
                raise Exception(f"Error {response.status_code}: {response.json()}")

        except requests.Timeout:
            if attempt < max_retries - 1:
                print(f"Timeout. Retrying... ({attempt + 1}/{max_retries})")
                continue
            else:
                raise

    raise Exception("Max retries exceeded")

Rate Limiting

Rate Limit Rules

Plan Rate Limit Burst Quota
Free 2 req/min 5 10/day
Basic 10 req/min 20 3,000/month
Pro 30 req/min 60 20,000/month
Enterprise Custom Custom Custom

Rate Limit Headers

Every response includes rate limit information:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1672531200
Header Description
X-RateLimit-Limit Maximum requests per time window
X-RateLimit-Remaining Remaining requests in current window
X-RateLimit-Reset Unix timestamp when limit resets

Handling Rate Limits

import requests
import time

def wait_for_rate_limit_reset(response):
    """Wait until rate limit resets"""
    if response.status_code == 429:
        reset_time = int(response.headers.get('X-RateLimit-Reset', 0))
        current_time = int(time.time())
        wait_time = max(0, reset_time - current_time)

        print(f"Rate limited. Waiting {wait_time}s for reset...")
        time.sleep(wait_time + 1)  # Add 1s buffer
        return True
    return False

Best Practices

  1. Check remaining quota before making requests
  2. Implement exponential backoff for retries
  3. Cache results to avoid duplicate requests
  4. Use batch endpoints (when available) for multiple images
  5. Upgrade your plan if consistently hitting limits

Best Practices

Performance Optimization

1. Image Preprocessing

from PIL import Image

def optimize_image(image_path, max_size=2048):
    """Resize large images before upload"""
    img = Image.open(image_path)

    # Check if resize needed
    if max(img.size) > max_size:
        ratio = max_size / max(img.size)
        new_size = tuple(int(dim * ratio) for dim in img.size)
        img = img.resize(new_size, Image.LANCZOS)

    # Convert to RGB if needed
    if img.mode != 'RGB':
        img = img.convert('RGB')

    # Save optimized
    output = "optimized.jpg"
    img.save(output, quality=95, optimize=True)
    return output

2. Concurrent Processing

from concurrent.futures import ThreadPoolExecutor
import requests

def process_batch(image_paths, api_key, max_workers=4):
    """Process multiple images concurrently"""
    def process_one(path):
        headers = {"X-API-Key": api_key}
        with open(path, "rb") as f:
            response = requests.post(
                "https://api.iopaint.com/api/v1/remove-watermark",
                headers=headers,
                files={"image": f}
            )
        return path, response

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        results = list(executor.map(process_one, image_paths))

    return results

3. Connection Reuse

import requests

# Reuse session for multiple requests
session = requests.Session()
session.headers.update({"X-API-Key": api_key})

for image_path in image_paths:
    with open(image_path, "rb") as f:
        response = session.post(
            "https://api.iopaint.com/api/v1/remove-watermark",
            files={"image": f}
        )

Security

Environment Variables

# .env file
IOPAINT_API_KEY=sk_live_1234567890abcdef

# .gitignore
.env
import os
from dotenv import load_dotenv

load_dotenv()
api_key = os.getenv("IOPAINT_API_KEY")

API Key Rotation

# Rotate keys periodically
def rotate_api_key():
    old_key = os.getenv("IOPAINT_API_KEY")
    new_key = generate_new_key()  # From dashboard

    # Test new key
    test_response = requests.get(
        "https://api.iopaint.com/api/v1/health",
        headers={"X-API-Key": new_key}
    )

    if test_response.status_code == 200:
        # Update environment
        update_env("IOPAINT_API_KEY", new_key)
        # Revoke old key from dashboard
        revoke_key(old_key)

Cost Optimization

1. Cache Results

import hashlib
import os

def get_cached_result(image_path):
    """Check if result already cached"""
    # Generate cache key from file content
    with open(image_path, "rb") as f:
        file_hash = hashlib.md5(f.read()).hexdigest()

    cache_path = f"cache/{file_hash}.png"
    if os.path.exists(cache_path):
        return cache_path
    return None

def process_with_cache(image_path, api_key):
    """Process with caching"""
    # Check cache first
    cached = get_cached_result(image_path)
    if cached:
        print(f"✓ Using cached result: {cached}")
        return cached

    # Process via API
    result = remove_watermark(image_path, api_key)

    # Save to cache
    with open(image_path, "rb") as f:
        file_hash = hashlib.md5(f.read()).hexdigest()
    cache_path = f"cache/{file_hash}.png"
    with open(cache_path, "wb") as f:
        f.write(result)

    return cache_path

2. Monitor Usage

def check_quota_before_request(api_key):
    """Check quota before making expensive requests"""
    headers = {"X-API-Key": api_key}
    response = requests.get(
        "https://api.iopaint.com/api/v1/stats",
        headers=headers
    )

    stats = response.json()
    quota_used = stats['total']
    plan_limit = 3000  # Basic plan

    remaining = plan_limit - quota_used
    if remaining < 100:
        print(f"⚠️ Warning: Only {remaining} requests remaining!")

    return remaining > 0

SDKs & Libraries

Official SDKs

Python

pip install iopaint-sdk
from iopaint import IOPaintClient

client = IOPaintClient(api_key="your_api_key")

# Simple usage
result = client.remove_watermark("image.jpg")

# With options
result = client.remove_watermark(
    image="image.jpg",
    mask="mask.png",
    output="result.png"
)

# Batch processing
results = client.batch_process(
    images=["img1.jpg", "img2.jpg"],
    output_dir="./results"
)

JavaScript/TypeScript

npm install iopaint-sdk
const { IOPaintClient } = require('iopaint-sdk');

const client = new IOPaintClient({
    apiKey: process.env.IOPAINT_API_KEY
});

// Simple usage
await client.removeWatermark('image.jpg', 'result.png');

// With mask
await client.removeWatermark('image.jpg', 'result.png', {
    mask: 'mask.png'
});

Community Libraries

Language Library Author
Go iopaint-go Community
Ruby iopaint-rb Community
Java iopaint-java Community
PHP iopaint-php Community

Changelog

v1.0.0 (2025-11-28)

Initial Release

  • /api/v1/remove-watermark endpoint
  • /api/v1/health endpoint
  • /api/v1/stats endpoint
  • API key authentication
  • Rate limiting
  • Support for JPEG, PNG, WebP
  • Optional mask support
  • Processing time metrics

Coming Soon

  • 🔜 /api/v1/batch - Batch processing endpoint
  • 🔜 /api/v1/detect - Automatic watermark detection
  • 🔜 Webhook callbacks for async processing
  • 🔜 Additional models (SD, SDXL)
  • 🔜 Custom model training

Support

Resources

Contact

SLA (Service Level Agreement)

Plan Uptime Support Response
Free 95% Community
Basic 99% 48 hours
Pro 99.5% 24 hours
Enterprise 99.9% 4 hours

Terms of Service

By using the IOPaint API, you agree to our Terms of Service.

Privacy Policy

We respect your privacy. See our Privacy Policy.

Data Processing

  • Images are processed in memory and not stored
  • Uploaded images are deleted immediately after processing
  • We do not train models on your data
  • Logs contain only metadata (no image content)

Usage Restrictions

Allowed:

  • Removing watermarks from your own content
  • Restoring old photos
  • Object removal for creative projects
  • Commercial use (with appropriate plan)

Prohibited:

  • Removing copyright protection
  • Processing illegal content
  • Violating third-party rights
  • Automated scraping without permission

© 2025 IOPaint. All rights reserved.

Last updated: 2025-11-28