Skip to content

Advanced Image Processing

Professional-grade image processing pipeline powered by state-of-the-art AI models. Color grade like a Hollywood colorist, restore degraded photos, generate depth maps, and tag images with semantic understanding — all through a single unified API.

All endpoints accept image URLs and return processed image URLs. Results are stored for 24 hours.

Endpoints

EndpointDescriptionCredits
POST /v1/images/color-gradeProfessional color grading with presets or manual controls1
POST /v1/images/enhanceAI auto-enhancement (exposure, sharpness, color balance)1
POST /v1/images/denoiseAI noise reduction preserving detail1
POST /v1/images/colorizeColorize black & white images2
POST /v1/images/face-restoreRestore degraded faces (CodeFormer/GFPGAN)2
POST /v1/images/depth-mapMonocular depth estimation2
POST /v1/images/clip-tagAI auto-tagging with CLIP1
POST /v1/images/clip-embedGenerate CLIP vector embeddings1
POST /v1/images/batchBatch process multiple images1 per image

Authentication: Bearer token (API key)
Base URL: https://apis.fotohub.app


Color Grading

POST /v1/images/color-grade

Apply professional color grading to any image. Choose from cinematic presets used in film production, or dial in precise manual adjustments for temperature, tint, saturation, contrast, shadows, and highlights.

Parameters

ParameterTypeRequiredDefaultDescription
image_urlstringYesURL of the image to process. Must be publicly accessible. Supports JPEG, PNG, WebP. Max 50MB.
presetstringNoColor grading preset. Options: cinematic, warm, cool, vintage, noir, teal-orange, pastel. Overrides manual controls when set.
temperaturefloatNo0.0Color temperature adjustment. Range: -1.0 (cool/blue) to 1.0 (warm/amber).
tintfloatNo0.0Green-magenta tint shift. Range: -1.0 (green) to 1.0 (magenta).
saturationfloatNo0.0Saturation adjustment. Range: -1.0 (desaturated) to 1.0 (vivid).
contrastfloatNo0.0Contrast adjustment. Range: -1.0 (flat) to 1.0 (punchy).
shadowsfloatNo0.0Shadow level adjustment. Range: -1.0 (crushed blacks) to 1.0 (lifted shadows).
highlightsfloatNo0.0Highlight level adjustment. Range: -1.0 (pulled highlights) to 1.0 (bright highlights).
intensityfloatNo1.0Blend intensity of the grade. Range: 0.0 (no effect) to 1.0 (full effect). Useful for subtle grades.
output_formatstringNojpgOutput format: jpg, png, webp.

Preset Reference

PresetLookBest For
cinematicTeal shadows, warm highlights, crushed blacksFilm-like scenes, landscapes
warmGolden tones, lifted shadowsPortraits, golden hour
coolBlue tones, high contrastTech, winter, moody
vintageFaded blacks, warm midtones, grainRetro, nostalgia
noirDesaturated, high contrast, darkDrama, B&W film look
teal-orangeComplementary teal/orange splitBlockbuster cinema
pastelLow saturation, soft tonesFashion, editorial

Response

json
{
  "output_url": "https://s1.fotohub.app/storage/v1/object/public/photos/processed/cg_a1b2c3d4.jpg",
  "credits_used": 1,
  "billing": {
    "method": "credits",
    "credits_used": 1,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "applied": {
    "preset": "cinematic",
    "intensity": 1.0
  },
  "processing_time_ms": 890
}

Reading the billing block

method is credits while your plan's monthly allowance covers the request, and usd_charged is 0 because no money moved. Once the allowance is exhausted the same call returns "method": "wallet" with the USD amount in usd_charged (see Pricing for the per-operation figures). pln_charged is a legacy mirror of the same charge -- read usd_charged.

Code Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="fh_live_your_api_key")

# Using a preset
result = client.images.color_grade(
    image_url="https://example.com/photo.jpg",
    preset="cinematic"
)

# Manual controls
result = client.images.color_grade(
    image_url="https://example.com/photo.jpg",
    temperature=0.3,
    contrast=0.2,
    shadows=0.1,
    highlights=-0.1,
    saturation=0.15,
    intensity=0.8
)

print(result.output_url)
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

// Using a preset
const result = await client.images.colorGrade({
  imageUrl: "https://example.com/photo.jpg",
  preset: "teal-orange",
});

// Manual controls
const result = await client.images.colorGrade({
  imageUrl: "https://example.com/photo.jpg",
  temperature: 0.3,
  contrast: 0.2,
  shadows: 0.1,
  highlights: -0.1,
  saturation: 0.15,
  intensity: 0.8,
});

console.log(result.outputUrl);
bash
curl -X POST https://apis.fotohub.app/v1/images/color-grade \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/photo.jpg",
    "preset": "cinematic",
    "intensity": 0.8
  }'

AI Enhancement

POST /v1/images/enhance

Automatic AI-powered enhancement that intelligently adjusts exposure, white balance, sharpness, color vibrancy, and dynamic range. Choose a scene-specific mode for optimized results.

Parameters

ParameterTypeRequiredDefaultDescription
image_urlstringYesURL of the image to process. Must be publicly accessible. Supports JPEG, PNG, WebP. Max 50MB.
modestringNoautoEnhancement mode. Options: auto, portrait, landscape, product, food.
strengthfloatNo0.7Enhancement strength. Range: 0.0 (subtle) to 1.0 (maximum).
sharpenbooleanNotrueApply intelligent sharpening after enhancement.
output_formatstringNojpgOutput format: jpg, png, webp.

Enhancement Modes

  • auto — Analyzes content and applies balanced adjustments.
  • portrait — Optimizes skin tones, softens background, balances lighting on faces.
  • landscape — Boosts sky blues, enhances greens, increases clarity.
  • product — Neutral white balance, removes color casts, clean look.
  • food — Warm tones, vibrant colors, appetizing appearance.

Response

json
{
  "output_url": "https://s1.fotohub.app/storage/v1/object/public/photos/processed/enh_b2c3d4e5.jpg",
  "credits_used": 1,
  "billing": {
    "method": "credits",
    "credits_used": 1,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "adjustments_applied": {
    "exposure": 0.15,
    "white_balance": "corrected",
    "sharpness": 0.3,
    "vibrance": 0.2,
    "dynamic_range": "expanded"
  },
  "processing_time_ms": 1240
}

Code Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="fh_live_your_api_key")

result = client.images.enhance(
    image_url="https://example.com/portrait.jpg",
    mode="portrait",
    strength=0.8
)

print(result.output_url)
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

const result = await client.images.enhance({
  imageUrl: "https://example.com/portrait.jpg",
  mode: "portrait",
  strength: 0.8,
});

console.log(result.outputUrl);
bash
curl -X POST https://apis.fotohub.app/v1/images/enhance \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/portrait.jpg",
    "mode": "portrait",
    "strength": 0.8
  }'

AI Denoising

POST /v1/images/denoise

Advanced AI noise reduction that removes grain, compression artifacts, and sensor noise while preserving fine details and textures. Ideal for low-light photos, high-ISO images, and heavily compressed files.

Parameters

ParameterTypeRequiredDefaultDescription
image_urlstringYesURL of the image to process. Must be publicly accessible. Supports JPEG, PNG, WebP. Max 50MB.
strengthfloatNo0.5Denoising strength. Range: 0.0 (light) to 1.0 (aggressive). Higher values remove more noise but may soften fine details.
preserve_detailbooleanNotrueWhen true, uses detail-aware denoising that protects edges and textures.
output_formatstringNojpgOutput format: jpg, png, webp.

Response

json
{
  "output_url": "https://s1.fotohub.app/storage/v1/object/public/photos/processed/dn_c3d4e5f6.jpg",
  "credits_used": 1,
  "billing": {
    "method": "credits",
    "credits_used": 1,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "noise_level_detected": "high",
  "processing_time_ms": 1680
}

Code Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="fh_live_your_api_key")

result = client.images.denoise(
    image_url="https://example.com/noisy-photo.jpg",
    strength=0.7,
    preserve_detail=True
)

print(result.output_url)
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

const result = await client.images.denoise({
  imageUrl: "https://example.com/noisy-photo.jpg",
  strength: 0.7,
  preserveDetail: true,
});

console.log(result.outputUrl);
bash
curl -X POST https://apis.fotohub.app/v1/images/denoise \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/noisy-photo.jpg",
    "strength": 0.7,
    "preserve_detail": true
  }'

Colorize B&W Images

POST /v1/images/colorize

Automatically colorize black and white or grayscale images using deep learning. The model understands scene context, common object colors, and historical color palettes to produce natural, realistic colorization.

Parameters

ParameterTypeRequiredDefaultDescription
image_urlstringYesURL of the B&W or grayscale image. Must be publicly accessible. Supports JPEG, PNG, WebP. Max 50MB.
saturationfloatNo1.0Output saturation multiplier. Range: 0.5 (muted) to 2.0 (vivid). Default produces natural colors.
artisticbooleanNofalseWhen true, allows more creative/stylized colorization rather than strictly realistic.
output_formatstringNojpgOutput format: jpg, png, webp.

Response

json
{
  "output_url": "https://s1.fotohub.app/storage/v1/object/public/photos/processed/col_d4e5f6g7.jpg",
  "credits_used": 2,
  "billing": {
    "method": "credits",
    "credits_used": 2,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "processing_time_ms": 3450
}

Code Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="fh_live_your_api_key")

result = client.images.colorize(
    image_url="https://example.com/old-bw-photo.jpg",
    saturation=1.2
)

print(result.output_url)
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

const result = await client.images.colorize({
  imageUrl: "https://example.com/old-bw-photo.jpg",
  saturation: 1.2,
});

console.log(result.outputUrl);
bash
curl -X POST https://apis.fotohub.app/v1/images/colorize \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/old-bw-photo.jpg",
    "saturation": 1.2
  }'

Face Restoration

POST /v1/images/face-restore

Restore degraded, blurry, or low-resolution faces using state-of-the-art face restoration models. Recovers facial details, fixes artifacts, and produces sharp, natural-looking faces from heavily degraded inputs.

Parameters

ParameterTypeRequiredDefaultDescription
image_urlstringYesURL of the image with degraded faces. Must be publicly accessible. Supports JPEG, PNG, WebP. Max 50MB.
modelstringNocodeformerRestoration model. Options: codeformer (best quality, slower), gfpgan (faster, good quality).
fidelityfloatNo0.7Balance between quality and fidelity to original. Range: 0.0 (max quality, less faithful) to 1.0 (max fidelity, less enhancement). Only applies to CodeFormer.
upscaleintegerNo1Upscale factor for the output. Options: 1 (original size), 2 (2x), 4 (4x).
background_enhancebooleanNofalseWhen true, also enhances the non-face regions of the image.
output_formatstringNojpgOutput format: jpg, png, webp.

Model Comparison

ModelQualitySpeedBest For
codeformerExcellent~3s per faceSeverely degraded faces, old photos, heavy compression
gfpganGood~1.5s per faceLight degradation, batch processing, real-time apps

Response

json
{
  "output_url": "https://s1.fotohub.app/storage/v1/object/public/photos/processed/fr_e5f6g7h8.jpg",
  "credits_used": 2,
  "billing": {
    "method": "credits",
    "credits_used": 2,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "faces_detected": 3,
  "faces_restored": 3,
  "model_used": "codeformer",
  "processing_time_ms": 4120
}

Code Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="fh_live_your_api_key")

result = client.images.face_restore(
    image_url="https://example.com/old-family-photo.jpg",
    model="codeformer",
    fidelity=0.6,
    upscale=2,
    background_enhance=True
)

print(f"Restored {result.faces_restored} faces")
print(result.output_url)
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

const result = await client.images.faceRestore({
  imageUrl: "https://example.com/old-family-photo.jpg",
  model: "codeformer",
  fidelity: 0.6,
  upscale: 2,
  backgroundEnhance: true,
});

console.log(`Restored ${result.facesRestored} faces`);
console.log(result.outputUrl);
bash
curl -X POST https://apis.fotohub.app/v1/images/face-restore \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/old-family-photo.jpg",
    "model": "codeformer",
    "fidelity": 0.6,
    "upscale": 2,
    "background_enhance": true
  }'

Depth Map Estimation

POST /v1/images/depth-map

Generate monocular depth maps from single images using state-of-the-art depth estimation models. Outputs a grayscale depth image where brightness represents distance from the camera. Useful for 3D effects, parallax, bokeh simulation, and scene understanding.

Parameters

ParameterTypeRequiredDefaultDescription
image_urlstringYesURL of the image to process. Must be publicly accessible. Supports JPEG, PNG, WebP. Max 50MB.
modelstringNomidasDepth estimation model. Options: midas (general-purpose, outdoor/indoor), zoedepth (metric depth, best for indoor scenes).
output_typestringNograyscaleOutput format type. Options: grayscale (standard depth map), colored (viridis colormap visualization), raw (16-bit PNG with metric depth values).
invertbooleanNofalseInvert depth values (near=dark, far=bright instead of default near=bright, far=dark).
output_formatstringNopngOutput file format: png, webp.

Model Comparison

ModelTypeAccuracyBest For
midasRelative depthHighGeneral scenes, outdoor, landscapes, mixed content
zoedepthMetric depthVery HighIndoor scenes, room layout, furniture, architecture

Response

json
{
  "output_url": "https://s1.fotohub.app/storage/v1/object/public/photos/processed/dm_f6g7h8i9.png",
  "credits_used": 2,
  "billing": {
    "method": "credits",
    "credits_used": 2,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "model_used": "midas",
  "depth_range": {
    "min": 0.0,
    "max": 1.0
  },
  "processing_time_ms": 2180
}

Code Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="fh_live_your_api_key")

# General depth map
result = client.images.depth_map(
    image_url="https://example.com/landscape.jpg",
    model="midas",
    output_type="colored"
)

# Indoor metric depth
result = client.images.depth_map(
    image_url="https://example.com/room.jpg",
    model="zoedepth",
    output_type="raw"
)

print(result.output_url)
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

const result = await client.images.depthMap({
  imageUrl: "https://example.com/landscape.jpg",
  model: "midas",
  outputType: "colored",
});

console.log(result.outputUrl);
bash
curl -X POST https://apis.fotohub.app/v1/images/depth-map \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/landscape.jpg",
    "model": "midas",
    "output_type": "colored"
  }'

CLIP Auto-Tagging

POST /v1/images/clip-tag

Automatically tag images with descriptive labels using OpenAI's CLIP model. Returns ranked tags with confidence scores covering objects, scenes, styles, colors, and activities detected in the image.

Parameters

ParameterTypeRequiredDefaultDescription
image_urlstringYesURL of the image to tag. Must be publicly accessible. Supports JPEG, PNG, WebP. Max 50MB.
modelstringNoclip-vit-largeCLIP model variant. Options: clip-vit-large (more accurate, slower), clip-vit-base (faster, slightly less accurate).
max_tagsintegerNo20Maximum number of tags to return. Range: 1–50.
thresholdfloatNo0.15Minimum confidence threshold for returned tags. Range: 0.0–1.0. Lower values return more tags.
categoriesarrayNoallFilter tags by category. Options: objects, scenes, styles, colors, activities, emotions.

Response

json
{
  "tags": [
    { "label": "sunset", "confidence": 0.94, "category": "scenes" },
    { "label": "beach", "confidence": 0.91, "category": "scenes" },
    { "label": "orange", "confidence": 0.87, "category": "colors" },
    { "label": "silhouette", "confidence": 0.82, "category": "objects" },
    { "label": "romantic", "confidence": 0.76, "category": "emotions" },
    { "label": "photography", "confidence": 0.71, "category": "styles" },
    { "label": "walking", "confidence": 0.68, "category": "activities" }
  ],
  "model_used": "clip-vit-large",
  "credits_used": 1,
  "billing": {
    "method": "credits",
    "credits_used": 1,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "processing_time_ms": 520
}

Code Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="fh_live_your_api_key")

result = client.images.clip_tag(
    image_url="https://example.com/vacation-photo.jpg",
    max_tags=15,
    threshold=0.2,
    categories=["objects", "scenes", "activities"]
)

for tag in result.tags:
    print(f"{tag.label}: {tag.confidence:.2f}")
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

const result = await client.images.clipTag({
  imageUrl: "https://example.com/vacation-photo.jpg",
  maxTags: 15,
  threshold: 0.2,
  categories: ["objects", "scenes", "activities"],
});

result.tags.forEach((tag) => {
  console.log(`${tag.label}: ${tag.confidence.toFixed(2)}`);
});
bash
curl -X POST https://apis.fotohub.app/v1/images/clip-tag \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/vacation-photo.jpg",
    "max_tags": 15,
    "threshold": 0.2,
    "categories": ["objects", "scenes", "activities"]
  }'

CLIP Embeddings

POST /v1/images/clip-embed

Generate dense vector embeddings from images using CLIP. Returns a 512 or 768-dimensional float vector that captures semantic meaning of the image. Use these embeddings for visual similarity search, content-based recommendations, clustering, deduplication, and content moderation.

Parameters

ParameterTypeRequiredDefaultDescription
image_urlstringYesURL of the image to embed. Must be publicly accessible. Supports JPEG, PNG, WebP. Max 50MB.
modelstringNoclip-vit-largeCLIP model variant. clip-vit-large returns 768-dim vectors. clip-vit-base returns 512-dim vectors.
normalizebooleanNotrueL2-normalize the embedding vector (recommended for cosine similarity search).

Use Cases for CLIP Embeddings

  • Visual search — Find visually similar images in your library by comparing embedding distances.
  • Content moderation — Compare image embeddings against known violation embeddings.
  • Auto-categorization — Cluster images by semantic similarity without manual labeling.
  • Deduplication — Detect near-duplicate images even with crops, filters, or compression differences.
  • Cross-modal search — Combine with text embeddings (same CLIP space) to search images by text query.

Response

json
{
  "embedding": [0.0234, -0.0891, 0.0452, 0.1123, ...],
  "dimensions": 768,
  "model_used": "clip-vit-large",
  "normalized": true,
  "credits_used": 1,
  "billing": {
    "method": "credits",
    "credits_used": 1,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "processing_time_ms": 380
}

Code Examples

python
from fotohub import FotoHub
import numpy as np

client = FotoHub(api_key="fh_live_your_api_key")

# Generate embedding
result = client.images.clip_embed(
    image_url="https://example.com/product.jpg",
    model="clip-vit-large"
)

embedding = np.array(result.embedding)
print(f"Embedding shape: {embedding.shape}")  # (768,)

# Compare similarity between two images
result_a = client.images.clip_embed(image_url="https://example.com/img_a.jpg")
result_b = client.images.clip_embed(image_url="https://example.com/img_b.jpg")

similarity = np.dot(result_a.embedding, result_b.embedding)
print(f"Cosine similarity: {similarity:.4f}")
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

// Generate embedding
const result = await client.images.clipEmbed({
  imageUrl: "https://example.com/product.jpg",
  model: "clip-vit-large",
});

console.log(`Dimensions: ${result.dimensions}`); // 768

// Compare two images
const a = await client.images.clipEmbed({ imageUrl: "https://example.com/img_a.jpg" });
const b = await client.images.clipEmbed({ imageUrl: "https://example.com/img_b.jpg" });

const similarity = a.embedding.reduce(
  (sum, val, i) => sum + val * b.embedding[i], 0
);
console.log(`Cosine similarity: ${similarity.toFixed(4)}`);
bash
curl -X POST https://apis.fotohub.app/v1/images/clip-embed \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/product.jpg",
    "model": "clip-vit-large",
    "normalize": true
  }'

Batch Processing

POST /v1/images/batch

Process multiple images in a single request with one or more operations applied in sequence. Supports up to 50 images per batch. Operations are applied as a pipeline — each operation's output feeds into the next.

Parameters

ParameterTypeRequiredDefaultDescription
imagesarrayYesArray of image URLs to process. Max 50 items. Each must be publicly accessible.
operationsarrayYesOrdered list of operations to apply to each image. Operations are applied sequentially as a pipeline.
parallelbooleanNotrueProcess images in parallel (faster) or sequentially (lower resource usage).
output_formatstringNojpgOutput format for all results: jpg, png, webp.

Operation Objects

Each operation in the operations array has a type and operation-specific parameters:

json
{
  "type": "enhance",
  "mode": "portrait",
  "strength": 0.8
}

Available operation types: color-grade, enhance, denoise, colorize, face-restore, depth-map, clip-tag, clip-embed.

Response

json
{
  "results": [
    {
      "input_url": "https://example.com/photo1.jpg",
      "output_url": "https://s1.fotohub.app/storage/v1/object/public/photos/processed/batch_001.jpg",
      "status": "success",
      "processing_time_ms": 2340
    },
    {
      "input_url": "https://example.com/photo2.jpg",
      "output_url": "https://s1.fotohub.app/storage/v1/object/public/photos/processed/batch_002.jpg",
      "status": "success",
      "processing_time_ms": 2180
    },
    {
      "input_url": "https://example.com/photo3.jpg",
      "output_url": null,
      "status": "error",
      "error": "Image URL returned 404"
    }
  ],
  "summary": {
    "total": 3,
    "succeeded": 2,
    "failed": 1
  },
  "credits_used": 4,
  "billing": {
    "method": "credits",
    "credits_used": 4,
    "usd_charged": 0,
    "pln_charged": 0
  },
  "total_processing_time_ms": 4890
}

Code Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="fh_live_your_api_key")

# Batch enhance + color grade a set of photos
result = client.images.batch(
    images=[
        "https://example.com/photo1.jpg",
        "https://example.com/photo2.jpg",
        "https://example.com/photo3.jpg",
        "https://example.com/photo4.jpg",
    ],
    operations=[
        {"type": "denoise", "strength": 0.5},
        {"type": "enhance", "mode": "portrait", "strength": 0.7},
        {"type": "color-grade", "preset": "cinematic"},
    ]
)

for item in result.results:
    if item.status == "success":
        print(f"Done: {item.output_url}")
    else:
        print(f"Failed: {item.error}")

print(f"Total credits: {result.credits_used}")
typescript
import { FotoHub } from "fotohub";

const client = new FotoHub({ apiKey: "fh_live_your_api_key" });

const result = await client.images.batch({
  images: [
    "https://example.com/photo1.jpg",
    "https://example.com/photo2.jpg",
    "https://example.com/photo3.jpg",
    "https://example.com/photo4.jpg",
  ],
  operations: [
    { type: "denoise", strength: 0.5 },
    { type: "enhance", mode: "portrait", strength: 0.7 },
    { type: "color-grade", preset: "cinematic" },
  ],
});

result.results.forEach((item) => {
  if (item.status === "success") {
    console.log(`Done: ${item.outputUrl}`);
  } else {
    console.log(`Failed: ${item.error}`);
  }
});

console.log(`Total credits: ${result.creditsUsed}`);
bash
curl -X POST https://apis.fotohub.app/v1/images/batch \
  -H "Authorization: Bearer fh_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "images": [
      "https://example.com/photo1.jpg",
      "https://example.com/photo2.jpg",
      "https://example.com/photo3.jpg"
    ],
    "operations": [
      {"type": "denoise", "strength": 0.5},
      {"type": "enhance", "mode": "portrait", "strength": 0.7},
      {"type": "color-grade", "preset": "cinematic"}
    ]
  }'

Pricing

OperationCreditsUSD CostDescription
Color Grade1$0.0536Preset or manual color grading
Enhance1$0.0536AI auto-enhancement
Denoise1$0.0536AI noise reduction
Colorize2$0.1072B&W to color
Face Restore2$0.1072CodeFormer/GFPGAN face restoration
Depth Map2$0.1072Monocular depth estimation
CLIP Tag1$0.0536Auto-tagging with confidence scores
CLIP Embed1$0.0536Vector embedding generation
Batch1/image$0.0536/imagePer-image cost, operations do not multiply cost

USD amounts are the wallet fallback at $0.0536 per credit, billed only after your plan's monthly credit allowance is used up.

Batch Pricing

Batch processing charges 1 credit per image regardless of how many operations are in the pipeline. A batch of 10 images with 3 operations each costs 10 credits total, not 30.


Best Practices

Image Quality

  • Input resolution matters — Higher resolution inputs produce better results for all operations. Minimum recommended: 512x512px.
  • Use appropriate formats — Submit JPEG for photos, PNG for graphics with transparency. WebP is accepted but JPEG typically produces best results for photographic content.
  • Check file size — Max 50MB per image. For batch operations, ensure all URLs are accessible and return images (not HTML error pages).

Color Grading Workflow

  • Start with a preset, then adjust intensity to blend it down for subtlety.
  • For consistent series (wedding albums, product shoots), apply the same preset and manual settings via batch processing.
  • Use temperature and tint for white balance correction before applying creative grades.

Face Restoration

  • Use codeformer with fidelity=0.5 for severely degraded faces (old scanned photos, extreme compression).
  • Use gfpgan for light touch-ups where speed matters.
  • Enable background_enhance=true only when the entire image needs restoration, not just faces.
  • For group photos, both models handle multiple faces automatically.
  • Always use normalize=true (default) for cosine similarity comparisons.
  • Store embeddings in a vector database (pgvector, Pinecone, Qdrant) for efficient similarity search.
  • Use clip-vit-large (768-dim) for production search systems — the accuracy improvement over clip-vit-base (512-dim) is significant.
  • Embeddings are deterministic — same image + same model always produces the same vector.

Batch Processing

  • Keep batches under 50 images for optimal throughput.
  • Use parallel=true (default) for independent images. Use parallel=false only if you hit rate limits.
  • Order operations logically: denoise first, then enhance, then color grade. Denoising after color grading can remove intended grain.
  • Failed images in a batch do not stop processing of remaining images. Always check the status field per result.

Error Handling

  • All endpoints return standard HTTP error codes. See Errors for the full reference.
  • Common errors: 401 (invalid API key), 402 (insufficient credits), 422 (invalid parameters), 413 (image too large).
  • Batch operations return per-image errors in the response body even when the HTTP status is 200.