Skip to content

Adobe Firefly API

Adobe Firefly API Complete Reference

This section provides comprehensive examples for all Adobe Firefly API endpoints available in Vision Studio, including image generation, editing, and utility operations.

Prerequisites

import requests
import json
import base64

# Your API endpoint and key
API_URL = "http://localhost:8527/api/v1/firefly"
API_KEY = "your-api-key"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

Authentication

Get Access Token

Obtain an access token for Adobe Firefly API operations.

response = requests.post(
    f"{API_URL}/token",
    headers=headers
)

Image Generation

1. Generate Images

Create high-quality images using Adobe Firefly's various models and configurations.

Basic Image Generation with Image 3 Model
data = {
    "access_token": access_token,
    "x_model_version": "image3",
    "prompt": "A majestic mountain landscape with crystal-clear lake reflecting snow-capped peaks during golden hour",
    "content_class": "photo",
    "size": {
        "height": 2048,
        "width": 2048
    },
    "upsampler_type": "default"
}

response = requests.post(
    f"{API_URL}/image/generation/generate-image",
    headers=headers,
    json=data
)
Advanced Generation with Image 4 Ultra Model
data = {
    "access_token": access_token,
    "x_model_version": "image4_ultra",
    "prompt": "Ultra-detailed portrait of a wise elderly woman with intricate traditional jewelry",
    "content_class": "photo",
    "negative_prompt": "blurry, distorted, low quality, artificial",
    "prompt_biasing_locale_code": "en-US",
    "seeds": [1, 2, 3],  # Generate 3 variations with specific seeds
    "size": {
        "height": 2688,
        "width": 1536
    },
    "visual_intensity": 7,
    "upsampler_type": "default"
}

response = requests.post(
    f"{API_URL}/image/generation/generate-image",
    headers=headers,
    json=data
)
Art Style Generation
data = {
    "access_token": access_token,
    "x_model_version": "image3",
    "prompt": "Abstract geometric composition with vibrant colors and dynamic shapes",
    "content_class": "art",
    "size": {
        "height": 1792,
        "width": 2304
    },
    "visual_intensity": 9,
    "upsampler_type": "default"
}

response = requests.post(
    f"{API_URL}/image/generation/generate-image",
    headers=headers,
    json=data
)
Generation with Structure Reference
# First, upload a reference image for structure
structure_reference = {
    "source": {
        "url": "https://example.com/structure_reference.jpg"
    }
}

data = {
    "access_token": access_token,
    "x_model_version": "image3",
    "prompt": "Transform this composition into a futuristic cityscape",
    "content_class": "photo",
    "size": {
        "height": 1344,
        "width": 768
    },
    "structure": {
        "imageReference": structure_reference,
        "strength": 80  # 0-100, higher means stronger adherence to structure
    },
    "seeds": [42],
    "upsampler_type": "default"
}

response = requests.post(
    f"{API_URL}/image/generation/generate-image",
    headers=headers,
    json=data
)
Generation with Style Reference
# Style reference with presets
style_reference = {
    "source": {
        "url": "https://example.com/style_reference.jpg"
    }
}

data = {
    "access_token": access_token,
    "x_model_version": "image3",
    "prompt": "A serene garden scene with flowing water and lush vegetation",
    "content_class": "art",
    "size": {
        "height": 1152,
        "width": 896
    },
    "style": {
        "imageReference": style_reference,
        "strength": 65,
        "presets": ["impressionist", "vibrant"]  # Available presets for style
    },
    "visual_intensity": 6,
    "upsampler_type": "default"
}

response = requests.post(
    f"{API_URL}/image/generation/generate-image",
    headers=headers,
    json=data
)
Custom Model Generation
data = {
    "access_token": access_token,
    "x_model_version": "image3_custom",
    "custom_model_id": "your-custom-model-uuid-here",  # Required for custom models
    "prompt": "Generate an image in my custom style",
    "content_class": "photo",
    "size": {
        "height": 2048,
        "width": 2048
    },
    "seeds": [1, 2],  # Generate 2 variations
    "upsampler_type": "default"
}

response = requests.post(
    f"{API_URL}/image/generation/generate-image",
    headers=headers,
    json=data
)

2. Generate Similar Images (Variations)

Create variations of an existing image while maintaining its core characteristics.

# Reference image for variation
reference_image = {
    "source": {
        "url": "https://example.com/original_image.jpg"
        # Or use upload_id: "uploaded-uuid-from-upload-endpoint"
    }
}

data = {
    "access_token": access_token,
    "x_model_version": "image3",
    "image": reference_image,
    "seeds": [1, 2, 3, 4]  # Generate 4 variations
}

response = requests.post(
    f"{API_URL}/image/generation/generate-variation",
    headers=headers,
    json=data
)

Image Editing

1. Generate Product Background

Composite products into new background environments with precise placement control.

Basic Product Background
# Product image and mask
product_image = {
    "source": {
        "url": "https://example.com/product_cutout.png"
    }
}

mask_image = {
    "source": {
        "url": "https://example.com/product_mask.png"
    }
}

data = {
    "access_token": access_token,
    "prompt": "Modern minimalist kitchen with marble countertops and natural lighting",
    "image": product_image,
    "mask": mask_image,
    "content_class": "photo",
    "placement": {
        "alignment": {
            "horizontal": "center",
            "vertical": "center"
        },
        "insert": {
            "center": 0,
            "top": 0,
            "bottom": 0,
            "left": 0,
            "right": 0
        }
    },
    "seeds": [123],
    "size": {
        "height": 2048,
        "width": 2048
    }
}
Custom Placement Product Background
data = {
    "access_token": access_token,
    "prompt": "Luxurious bedroom setting with warm ambient lighting",
    "image": product_image,
    "mask": mask_image,
    "content_class": "photo",
    "placement": {
        "alignment": {
            "horizontal": "left",
            "vertical": "bottom"
        },
        "insert": {
            "center": 0,
            "top": 100,
            "bottom": 50,
            "left": 200,
            "right": 0
        }
    },
    "size": {
        "height": 1792,
        "width": 2304
    },
    "seeds": [456, 789]  # Generate 2 variations
}

response = requests.post(
    f"{API_URL}/image/editing/generate-product-background",
    headers=headers,
    json=data
)
Styled Product Background
# Style reference for the background
style_reference = {
    "source": {
        "url": "https://example.com/interior_style.jpg"
    }
}

data = {
    "access_token": access_token,
    "prompt": "Elegant living room with sophisticated decor",
    "image": product_image,
    "mask": mask_image,
    "content_class": "photo",
    "placement": {
        "alignment": {
            "horizontal": "right",
            "vertical": "top"
        },
        "insert": {
            "center": 0,
            "top": 0,
            "bottom": 100,
            "left": 0,
            "right": 150
        }
    },
    "style": {
        "imageReference": style_reference,
        "strength": 70,
        "presets": ["modern", "elegant"]
    },
    "size": {
        "height": 2688,
        "width": 1536
    }
}

response = requests.post(
    f"{API_URL}/image/editing/generate-product-background",
    headers=headers,
    json=data
)

2. Expand Image (Outpainting)

Extend images beyond their original boundaries with AI-generated content.

Basic Image Expansion
# Source image to expand
source_image = {
    "source": {
        "url": "https://example.com/portrait.jpg"
    }
}

# Mask defining expansion areas
expansion_mask = {
    "source": {
        "url": "https://example.com/expansion_mask.png"
    },
    "invert": False  # False means white areas will be expanded
}

data = {
    "access_token": access_token,
    "image": source_image,
    "mask": expansion_mask,
    "placement": {
        "alignment": {
            "horizontal": "center",
            "vertical": "center"
        },
        "insert": {
            "center": 0,
            "top": 200,      # Expand upward by 200px
            "bottom": 200,   # Expand downward by 200px
            "left": 300,     # Expand left by 300px
            "right": 300     # Expand right by 300px
        }
    },
    "prompt": "Natural forest background with tall pine trees",
    "seeds": [111, 222],
    "size": {
        "height": 2048,
        "width": 2048
    }
}

response = requests.post(
    f"{API_URL}/image/editing/expand-image",
    headers=headers,
    json=data
)
Selective Expansion
data = {
    "access_token": access_token,
    "image": source_image,
    "mask": expansion_mask,
    "placement": {
        "alignment": {
            "horizontal": "left",
            "vertical": "bottom"
        },
        "insert": {
            "center": 0,
            "top": 500,    # Expand only upward for sky
            "bottom": 0,
            "left": 0,
            "right": 0
        }
    },
    "prompt": "Dramatic cloudy sky with golden sunset",
    "seeds": [333]
}

response = requests.post(
    f"{API_URL}/image/editing/expand-image",
    headers=headers,
    json=data
)

3. Inpainting (Fill Image)

Fill specific areas of images with new AI-generated content.

Basic Inpainting
# Source image with areas to fill
source_image = {
    "source": {
        "url": "https://example.com/scene_with_gaps.jpg"
    }
}

# Mask defining areas to fill
fill_mask = {
    "source": {
        "url": "https://example.com/fill_mask.png"
    },
    "invert": False  # White areas will be filled
}

data = {
    "access_token": access_token,
    "image": source_image,
    "mask": fill_mask,
    "prompt": "Beautiful flowering garden with colorful roses and butterflies",
    "negative_prompt": "dead plants, wilted flowers, brown leaves",
    "prompt_biasing_locale_code": "en-US",
    "seeds": [777],
    "size": {
        "height": 2048,
        "width": 2048
    }
}

response = requests.post(
    f"{API_URL}/image/editing/inpaint",
    headers=headers,
    json=data
)
Advanced Inpainting with Multiple Variations
data = {
    "access_token": access_token,
    "image": source_image,
    "mask": fill_mask,
    "prompt": "Modern architectural elements with clean geometric lines",
    "negative_prompt": "cluttered, messy, old, weathered",
    "seeds": [100, 200, 300, 400],  # Generate 4 different fills
    "size": {
        "height": 1792,
        "width": 2304
    }
}

response = requests.post(
    f"{API_URL}/image/editing/inpaint",
    headers=headers,
    json=data
)
Content Removal Inpainting
# Remove objects by filling with background
data = {
    "access_token": access_token,
    "image": source_image,
    "mask": fill_mask,
    "prompt": None,  # No prompt for background filling
    "negative_prompt": "objects, people, text, signs",
    "seeds": [555],
    "size": {
        "height": 2048,
        "width": 2048
    }
}

response = requests.post(
    f"{API_URL}/image/editing/inpaint",
    headers=headers,
    json=data
)

Job Management

Check Job Status

Monitor the progress and retrieve results of asynchronous operations.

job_id = "your-job-id-from-generation-request"

response = requests.get(
    f"{API_URL}/status/{job_id}",
    headers={"access_token": access_token}
)

Cancel Job

Cancel a running generation job.

job_id = "your-job-id-to-cancel"

response = requests.put(
    f"{API_URL}/cancel/{job_id}",
    headers={"access_token": access_token}
)

File Upload

Upload Images

Upload images to Adobe's storage for use in generation and editing operations.

# Upload an image file
with open("your_image.jpg", "rb") as image_file:
    files = {"file": image_file}
    upload_headers = {"access_token": access_token}

    response = requests.post(
        f"{API_URL}/upload",
        headers=upload_headers,
        files=files
    )

Advanced Example: Concurrent Image Generation

Here's an example of making multiple concurrent generation requests using asyncio and aiohttp:

import asyncio
import aiohttp
import time

async def generate_image_async(session, prompt, request_id, access_token):
    """Generate a single image asynchronously."""
    url = f"{API_URL}/image/generation/generate-image"

    data = {
        "access_token": access_token,
        "x_model_version": "image3",
        "prompt": prompt,
        "content_class": "photo",
        "size": {
            "height": 1024,
            "width": 1024
        },
        "seeds": [request_id + 100],  # Use request_id to ensure unique seeds
        "upsampler_type": "default"
    }

    headers_async = {
        "X-API-Key": API_KEY,
        "Content-Type": "application/json"
    }

    start_time = time.time()

    try:
        async with session.post(url, headers=headers_async, json=data) as response:
            result = await response.json()
            duration = time.time() - start_time

            return {
                "request_id": request_id,
                "prompt": prompt,
                "status": response.status,
                "duration": duration,
                "result": result
            }
    except Exception as e:
        return {
            "request_id": request_id,
            "prompt": prompt,
            "status": -1,
            "duration": time.time() - start_time,
            "error": str(e)
        }

async def check_job_status_async(session, job_id, access_token):
    """Check job status asynchronously."""
    url = f"{API_URL}/status/{job_id}"

    headers_async = {
        "access_token": access_token
    }

    try:
        async with session.get(url, headers=headers_async) as response:
            result = await response.json()
            return {
                "job_id": job_id,
                "status": response.status,
                "result": result
            }
    except Exception as e:
        return {
            "job_id": job_id,
            "status": -1,
            "error": str(e)
        }

async def generate_multiple_images_concurrently():
    """Generate multiple images concurrently and monitor their completion."""

    # First, get access token
    token_response = requests.post(f"{API_URL}/token", headers=headers)
    if not token_response.json()["success"]:
        print("Failed to get access token")
        return

    access_token = token_response.json()["data"]["access_token"]

    prompts = [
        "A peaceful mountain lake surrounded by autumn foliage",
        "Modern architectural building with glass facade at sunset",
        "Vibrant street art mural with geometric patterns",
        "Cozy coffee shop interior with warm lighting",
        "Abstract digital art with flowing colors and shapes"
    ]

    # Configure session for concurrent requests
    timeout = aiohttp.ClientTimeout(total=300)  # 5 minute timeout
    connector = aiohttp.TCPConnector(limit=10)

    async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session:
        # Phase 1: Start all generation jobs concurrently
        print(f"Starting {len(prompts)} concurrent image generation requests...")
        start_time = time.time()

        generation_tasks = [
            generate_image_async(session, prompt, i, access_token)
            for i, prompt in enumerate(prompts)
        ]

        generation_results = await asyncio.gather(*generation_tasks)

        # Extract job IDs from successful requests
        job_ids = []
        for result in generation_results:
            if result["status"] == 200 and result["result"]["success"]:
                job_id = result["result"]["data"]["job_id"]
                job_ids.append(job_id)
                print(f"✅ Started job {job_id} for: {result['prompt'][:50]}...")
            else:
                error_msg = result.get('error', f"HTTP {result['status']}")
                print(f"❌ Failed to start: {result['prompt'][:50]}... - {error_msg}")

        if not job_ids:
            print("No jobs started successfully")
            return

        # Phase 2: Monitor job completion
        print(f"\nMonitoring {len(job_ids)} jobs for completion...")
        completed_jobs = []
        max_wait_time = 300  # 5 minutes maximum wait
        check_interval = 5   # Check every 5 seconds
        elapsed_time = 0

        while len(completed_jobs) < len(job_ids) and elapsed_time < max_wait_time:
            # Check status of all pending jobs
            pending_job_ids = [jid for jid in job_ids if jid not in completed_jobs]

            status_tasks = [
                check_job_status_async(session, job_id, access_token)
                for job_id in pending_job_ids
            ]

            status_results = await asyncio.gather(*status_tasks)

            for status_result in status_results:
                if status_result["status"] == 200:
                    job_data = status_result["result"]["data"]
                    job_status = job_data.get("status", "unknown")
                    job_id = status_result["job_id"]

                    if job_status == "completed":
                        completed_jobs.append(job_id)
                        # Get the generated images
                        outputs = job_data.get("outputs", [])
                        print(f"✅ Job {job_id} completed with {len(outputs)} images")
                        for i, output in enumerate(outputs):
                            if "image" in output and "url" in output["image"]:
                                print(f"   Image {i+1}: {output['image']['url']}")

                    elif job_status == "failed":
                        completed_jobs.append(job_id)  # Count as completed to stop waiting
                        error_msg = job_data.get("error", "Unknown error")
                        print(f"❌ Job {job_id} failed: {error_msg}")

            # Wait before next check if there are still pending jobs
            if len(completed_jobs) < len(job_ids):
                await asyncio.sleep(check_interval)
                elapsed_time += check_interval

        total_time = time.time() - start_time

        # Final summary
        successful_jobs = len([jid for jid in completed_jobs])
        print(f"\n📊 Summary:")
        print(f"   Total time: {total_time:.1f} seconds")
        print(f"   Jobs started: {len(job_ids)}")
        print(f"   Jobs completed: {successful_jobs}")

        if elapsed_time >= max_wait_time:
            remaining = len(job_ids) - len(completed_jobs)
            print(f"   ⚠️  {remaining} jobs still pending (timeout reached)")

# Run the concurrent generation
if __name__ == "__main__":
    asyncio.run(generate_multiple_images_concurrently())

This concurrent example demonstrates: - Two-phase approach: Start all generation jobs concurrently, then monitor completion - Proper session management with timeouts and connection limits - Job status monitoring with polling until completion - Comprehensive error handling for both generation and status checking - Performance metrics and detailed progress reporting - Realistic timeout handling for long-running generation tasks


Available Model Sizes

Image3 Model Sizes

  • 2048×2048 (Square)
  • 1024×1024 (Small Square)
  • 2304×1792 (Landscape)
  • 1792×2304 (Portrait)
  • 2688×1536 (Wide)
  • 2688×1512 (Wide Alt)
  • 1344×768 (Small Wide)
  • 1344×756 (Small Wide Alt)
  • 1152×896 (Medium Landscape)
  • 896×1152 (Medium Portrait)

Image4 Model Sizes

  • 2048×2048 (Square)
  • 2304×1792 (Landscape)
  • 1792×2304 (Portrait)
  • 2688×1536 (Wide)
  • 1440×2560 (Mobile Portrait)

Best Practices

  1. Use appropriate model versions: Choose between Image3, Image4 Standard, and Image4 Ultra based on quality requirements
  2. Manage seeds effectively: Use unique seeds for variations, consistent seeds for reproducibility
  3. Optimize placement parameters: Fine-tune alignment and insert values for precise product positioning
  4. Handle async operations: Always monitor job status for completion rather than assuming immediate results
  5. Upload management: Use upload endpoint for repeated use of images to avoid re-uploading
  6. Size constraints: Respect model-specific size limitations and file size limits (15MB max)
  7. Concurrent operations: Use proper session management and timeouts for concurrent requests
  8. Error handling: Implement robust retry logic for failed jobs and network issues