HiAPI
  • Models
  • Pricing
Search

Search HiAPI models, tools, and resources.

  • Models
  • Pricing
HiAPI

One API, All AI Models

Generate images, video, and audio with leading models through one production-ready API.

Get a free API key

AI Image API

  • All image models
  • GPT Image 2
  • Nano Banana 2
  • Seedream 5.0 Pro
  • Qwen Image 2.0 Pro
  • FLUX 1.1 Pro

AI Video API

  • All video models
  • Seedance 2.5
  • FLUX.3 Video
  • Seedance 2.0
  • Veo 3.1
  • Kling 3.0 Omni

AI Audio API

  • All audio models
  • MiniMax Music 2.6
  • MiniMax Music 1.5
  • ElevenLabs v3
  • Text to music
  • Text to speech

Product

  • Model marketplace
  • Playground
  • Pricing
  • Image API Cost Calculator
  • Free GPT Image 2 Generator
  • Free Nano Banana Image Generator
  • Outfit Preview
  • Product Photo Lab

Developers

  • Documentation
  • API Reference
  • Agent Skills
  • LLM integration index
  • Blog

Company

  • About
  • Contact support
  • Terms of Service
  • Privacy Policy

© 2026 hiapi. All rights reserved.

Open source on GitHubPython SDK on PyPI
  • Why flux-schnell for catalog work specifically
  • The shot list you're actually generating
  • One-shot: a single packshot in curl
  • Production: a batch generator in Python
  • Prompt template that gives you boring, useful packshots
  • Color / material variants without re-photographing
  • Connecting to your storefront
  • Cost math for planning
  • What flux-schnell will not do well
  • FAQ
TutorialJun 28, 2026

Generating Ecommerce Product Images with FLUX.1 [schnell] via the hiapi API

A working curl + Python guide for catalog packshots, lifestyle, and variants at $0.005 per image.

hiapihiapiflux-schnellimage-generationecommerce

Latest models

Explore models

Contents
  • Why flux-schnell for catalog work specifically
  • The shot list you're actually generating
  • One-shot: a single packshot in curl
  • Production: a batch generator in Python
  • Prompt template that gives you boring, useful packshots
  • Color / material variants without re-photographing
  • Connecting to your storefront
  • Cost math for planning
  • What flux-schnell will not do well
  • FAQ

Generate it with HiAPI

Choose a model, enter your prompt, and see the result.

HiAPI Blog

Related articles

HiAPI

Generate it with HiAPI

Catalog photography is the slowest part of launching a SKU online. Studio booking, a stylist, a lightbox, a retoucher — for a $24 mug it makes no sense. flux-schnell/text-to-image on hiapi gets you usable white-background packshots, lifestyle hero shots, and color/material variants for $0.005 per image and roughly 30 seconds end-to-end, which is the regime where you stop thinking about cost per shot and start thinking about prompts and prompt batches.

This guide walks the exact workflow: the four shot types you actually need for a product detail page, the prompt structure that keeps the model on a clean cyclorama instead of inventing a wooden table, how to batch 100 variants through /v1/tasks without melting your terminal, and the small list of things schnell will not do that you should plan around.

Why flux-schnell for catalog work specifically

There are higher-fidelity models on hiapi (flux-2, flux-1.1-pro, nano-banana-pro), and for the one hero image on a brand campaign you should use them. For a catalog the math is different:

  • A 200-SKU launch needs maybe 4 shots per SKU (white background, lifestyle, scale reference, top-down) = 800 images. At $0.005 that is $4. At $0.05 that is $40. At $0.17 that is $136.
  • schnell produces in 1–4 sampling steps, so end-to-end (queue + generation + download) lands around 30 seconds in our runs. flux-2 and nano-banana-pro are several times slower.
  • Catalog images are seen at 600px wide on a PDP and 200px in a grid. The fidelity headroom of a premium model is invisible at those sizes; prompt adherence and aspect-ratio sanity matter more.

The tradeoff is real: schnell is weaker on tiny readable text on labels, weaker on photoreal humans holding the product (use nano-banana-pro for that), and noticeably weaker on intricate brand logos. For "show me the product, on a clean background, in three colors, top-down and three-quarter" — its actual job — it is excellent.

The shot list you're actually generating

Before any prompts, decide what your PDP template needs. A useful starting set:

Shot typeAspect ratioUsed on
White-background packshot1:1PDP main image, grid thumbnail
Three-quarter studio4:3PDP gallery image 2
Lifestyle / contextual3:2PDP gallery, social ads
Top-down flatlay1:1PDP gallery, scale reference
Color/material variant grid1:1 per variantColor picker thumbnails

flux-schnell on hiapi supports 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9, auto. Anything else gets rejected at task creation.

One-shot: a single packshot in curl

The bare minimum to confirm your token works. This took 31 seconds end-to-end in my last run:

TOKEN="$HIAPI_API_KEY"

# 1. Create the task
TASK=$(curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-schnell/text-to-image",
    "input": {
      "prompt": "Product packshot: matte ceramic coffee mug, soft beige glaze, centered on seamless white cyclorama, soft diffused studio lighting, subtle contact shadow, 50mm photography, no props, ecommerce hero, clean negative space top and bottom",
      "aspect_ratio": "1:1"
    }
  }' | jq -r '.data.taskId')

echo "task: $TASK"

# 2. Poll until done (success | fail)
while true; do
  STATE=$(curl -s "https://api.hiapi.ai/v1/tasks/$TASK" \
    -H "Authorization: Bearer $TOKEN")
  STATUS=$(echo "$STATE" | jq -r '.data.status')
  echo "  status=$STATUS"
  [ "$STATUS" = "success" ] && break
  [ "$STATUS" = "fail" ] && { echo "$STATE" | jq '.data.error'; exit 1; }
  sleep 4
done

# 3. Download (output URLs expire; grab them right away)
URL=$(echo "$STATE" | jq -r '.data.output[0].url')
curl -s -o packshot.jpg "$URL"
echo "saved packshot.jpg"

Important quirk for flux-schnell specifically: the model's input schema accepts aspect_ratio but rejects resolution. Other image models on hiapi (e.g. flux-2, nano-banana-pro) accept both. If you submit {"aspect_ratio": "1:1", "resolution": "1K"} to flux-schnell you'll get:

{
  "code": 400,
  "message": "additional properties not allowed: resolution"
}

Strip resolution. You don't need it — schnell outputs at a model-default size for the ratio you picked.

Production: a batch generator in Python

A real catalog job submits many tasks, downloads outputs as they finish, and retries the fail cases. This is the script we use for prototyping a SKU range:

"""Batch packshot generator for flux-schnell on hiapi.

Reads a CSV of (sku, prompt, aspect_ratio), submits all jobs, polls in parallel,
downloads finished outputs to ./out/{sku}.jpg. Total cost = $0.005 * len(csv).
"""
import csv
import json
import os
import subprocess
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path

API = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]
OUT = Path("./out"); OUT.mkdir(exist_ok=True)


def _post(path, body):
    r = subprocess.run(
        ["curl", "-s", "-X", "POST", path,
         "-H", f"Authorization: Bearer {TOKEN}",
         "-H", "Content-Type: application/json",
         "-d", json.dumps(body)],
        capture_output=True, text=True, timeout=60,
    )
    return json.loads(r.stdout)


def _get(path):
    r = subprocess.run(
        ["curl", "-s", path, "-H", f"Authorization: Bearer {TOKEN}"],
        capture_output=True, text=True, timeout=30,
    )
    return json.loads(r.stdout)


def render(sku: str, prompt: str, ratio: str) -> tuple[str, str]:
    """Submit → poll → download. Returns (sku, status). status='ok' or 'fail:<reason>'."""
    body = {"model": "flux-schnell/text-to-image",
            "input": {"prompt": prompt, "aspect_ratio": ratio}}
    resp = _post(API, body)
    task_id = (resp.get("data") or {}).get("taskId")
    if not task_id:
        return sku, f"fail:submit:{resp.get('message')}"

    deadline = time.time() + 180
    while time.time() < deadline:
        state = _get(f"{API}/{task_id}")
        data = state.get("data") or {}
        status = data.get("status")
        if status == "success":
            url = (data.get("output") or [{}])[0].get("url")
            if not url:
                return sku, "fail:no-output-url"
            subprocess.run(["curl", "-s", "-o", str(OUT / f"{sku}.jpg"), url],
                           timeout=60, check=True)
            return sku, "ok"
        if status == "fail":
            return sku, f"fail:model:{data.get('error', {}).get('code')}"
        time.sleep(4)
    return sku, "fail:timeout"


def main():
    rows = list(csv.DictReader(open("skus.csv")))
    print(f"submitting {len(rows)} renders (cost ${0.005 * len(rows):.3f})")
    with ThreadPoolExecutor(max_workers=8) as ex:
        futures = {ex.submit(render, r["sku"], r["prompt"], r["aspect_ratio"]): r
                   for r in rows}
        for f in as_completed(futures):
            sku, status = f.result()
            print(f"  {sku}: {status}")


if __name__ == "__main__":
    main()

A skus.csv row looks like:

sku,prompt,aspect_ratio
mug-beige-01,"Product packshot: matte ceramic mug, beige glaze, seamless white cyclorama, soft studio lighting, subtle contact shadow, 50mm photography, ecommerce hero, clean negative space",1:1
mug-charcoal-01,"Product packshot: matte ceramic mug, charcoal glaze, seamless white cyclorama, soft studio lighting, subtle contact shadow, 50mm photography, ecommerce hero, clean negative space",1:1

Notes on the production code:

  • ThreadPoolExecutor(max_workers=8) is a safe parallelism for schnell. Going higher just deepens the queue without finishing sooner.
  • The 180-second per-task timeout is conservative; in practice every successful task lands in 30–60s. Hitting the timeout means the task is stuck — see the hiapi task hang/timeout guide for the four causes.
  • We download immediately after success. The output[].url is a temporary link with an expireAt timestamp; do not store it in your CMS.

Prompt template that gives you boring, useful packshots

Catalog prompts are not creative prompts. You want the same lighting, the same background, the same camera, every time, varying only the product. A template:

Product packshot: {MATERIAL} {PRODUCT}, {COLOR} {FINISH},
{COMPOSITION},
{BACKGROUND},
{LIGHTING},
{LENS_NOTE},
ecommerce hero, no props, clean negative space {AREA}

Filled in:

Product packshot: matte ceramic coffee mug, soft beige glaze,
centered single subject filling about 60% of frame,
seamless white cyclorama background,
soft diffused studio lighting from the upper left, subtle contact shadow underneath,
shot on 50mm with shallow depth of field,
ecommerce hero, no props, clean negative space top and bottom

The order matters less than the structure. Things that consistently improve output:

  • "seamless white cyclorama" beats "white background" — the former cues studio infinity-curve lighting, the latter sometimes gets you a tablecloth.
  • "subtle contact shadow underneath" prevents the floating-product look.
  • "filling about 60% of frame" anchors the composition; without it, schnell will sometimes zoom way out or push the product to a corner.
  • "no props" prevents stray plates, leaves, or stationery showing up next to the mug.

For lifestyle variants, swap the background + lighting block:

... matte ceramic coffee mug, soft beige glaze, single subject filling about 40% of frame,
on a light oak countertop with morning sunlight from a kitchen window,
soft golden-hour rim lighting, gentle defocused background showing a blurred linen curtain,
shot on 35mm at f/2.8, lifestyle photography, no people, no other props

For top-down flatlay:

... single subject centered, top-down 90-degree angle, ceramic coffee mug, soft beige glaze,
on a light grey paper surface, soft even overhead lighting, soft shadow directly under the rim,
shot on 50mm, flatlay product photography, no props, clean negative space all sides, 1:1

These three prompts, run against the same SKU, give you a usable PDP gallery for the cost of $0.015.

Color / material variants without re-photographing

The reason schnell shines for ecommerce is variant generation. Once a prompt works for one color, you mass-produce the rest by string-substituting the color descriptor:

COLORS = [
    ("beige", "soft beige glaze"),
    ("charcoal", "deep charcoal matte glaze"),
    ("sage", "muted sage green glaze"),
    ("terracotta", "warm terracotta clay glaze"),
    ("cream", "off-white cream glaze with subtle speckle"),
]

TEMPLATE = (
    "Product packshot: matte ceramic coffee mug, {color_desc}, "
    "centered single subject filling about 60% of frame, "
    "seamless white cyclorama background, soft diffused studio lighting from the upper left, "
    "subtle contact shadow underneath, shot on 50mm, ecommerce hero, no props, "
    "clean negative space top and bottom"
)

rows = [{"sku": f"mug-{c}-01", "prompt": TEMPLATE.format(color_desc=desc),
         "aspect_ratio": "1:1"} for c, desc in COLORS]

Five variants at $0.005 = $0.025 for the entire color picker. The catch: schnell does not perfectly preserve the form factor across renders. The mug handle thickness, the lip curve, the proportion will drift slightly between colors. For a stylized product page that's fine. For pixel-identical variants you need reference-image conditioning, which means flux-1.1-pro with a reference image or nano-banana-pro, not schnell.

Connecting to your storefront

The output is a downloaded JPG file. From there, the path to a live PDP depends on your platform:

  • Shopify: POST /admin/api/2025-01/products/{id}/images.json with {"image": {"attachment": "<base64>"}}. Returns a CDN URL Shopify hosts.
  • WooCommerce: upload via WP Media Library (POST /wp-json/wp/v2/media), then PATCH the product with the returned media ID in images: [{id: ...}].
  • Headless / custom CMS: upload to your own object store (S3, R2, Cloudflare Images) and reference the resulting URL in your product record.

In every case, do the upload server-side, not client-side, so your hiapi key never reaches the browser.

Cost math for planning

At $0.005 per image, the budget is rarely the constraint — but it helps to think in batches:

BatchImagesCost
One SKU, 4 shots4$0.02
50-SKU launch, 4 shots each200$1.00
200-SKU catalog refresh800$4.00
Daily variant testing, 100/day for 30 days3,000$15.00

Token-side cost (the prompt) is free for image endpoints on hiapi — you pay per output image only.

What flux-schnell will not do well

Things to plan around before you commit:

  • Readable label text. If your packshot needs the brand wordmark legible, generate the base shot in schnell, then composite the real label PNG on top in your image editor. Asking schnell to render "with the word 'OAK ROAST' on the mug" produces gibberish about 80% of the time.
  • Hands holding the product. Anatomy on humans is schnell's weak spot. For lifestyle shots with a person, switch to nano-banana-pro or flux-1.1-pro.
  • Pixel-identical product across variants. Use a reference-image-capable model for that.
  • Sub-millimeter detail (jewelry, watches with visible hands, etched metal). Premium model territory.

For everything else on a PDP — backgrounds, lighting, color variants, contextual shots, mood — flux-schnell is the right tool, in the right price band, with the right turnaround. The whole loop fits inside a while true: poll; download script and a CSV of SKUs, and the cost stays small enough that you can iterate on prompts without budget meetings.

FAQ

Q: Can I send a reference image to flux-schnell? A: No. flux-schnell/text-to-image is text-to-image only — the input field accepts prompt and aspect_ratio, nothing else. For reference-conditioned variants, use flux-1.1-pro or nano-banana-pro, both of which accept image inputs on hiapi.

Q: What aspect ratios are supported? A: 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9, and auto. Any other ratio (e.g. 5:7, 2:1) gets rejected at task creation with an error pointing to the supported set.

Q: Why does my task creation 400 when I include resolution? A: flux-schnell only accepts aspect_ratio in its input. Other image models on hiapi (e.g. flux-2, nano-banana-pro) accept resolution (1K/2K/4K). For schnell, drop it.

Q: How long are the output URLs valid? A: Each output[].url carries an expireAt timestamp (typically tens of minutes). Download the image bytes as soon as status flips to success and store them in your own bucket — do not hot-link the temp URL into your product database.

Q: Can I run more than 8 concurrent tasks? A: Yes, but you won't finish faster in practice — schnell is already fast end-to-end and adding parallelism past ~8 just builds queue. For genuinely large batches (thousands), parallelize across multiple worker machines rather than threads in one process.

Q: How do I get pixel-identical variants of the same product? A: You don't, with schnell alone. Generate the master shot once, then use a reference-image-capable model (flux-1.1-pro or nano-banana-pro) for variant runs with the master as the reference. Cost goes up but form-factor consistency improves dramatically.

Latest models

View all models
  • GPT Image 2From $0.030/image
  • Nano Banana 2From $0.051/image
  • Seedream 5.0 ProFrom $0.050/image
  • Seedance 2.5From $0.231/s

Explore models

TextImageVideoAudio
Back to blog
GPT Image 2From $0.030/image
Nano Banana 2From $0.051/image
Seedream 5.0 ProFrom $0.050/image
Seedance 2.5From $0.231/s
View all models
TextChat and reasoning
ImageGenerate and edit
VideoText and image to video
AudioSpeech and music
Start generating
View model pricing
View all articles
How to Use the flux-3 API for Text-to-Video, Audio, and Continuation

How to Use the flux-3 API for Text-to-Video, Audio, and Continuation

minimax-music-3 API: curl & Python Guide

minimax-music-3 API: curl & Python Guide

How to use grok-imagine-image-2.0/image-to-image via the hiapi API: curl, Python, and a working request

How to use grok-imagine-image-2.0/image-to-image via the hiapi API: curl, Python, and a working request

How to Use grok-imagine-image-2.0/text-to-image via the hiapi API: curl, Python, and a Working Request

How to Use grok-imagine-image-2.0/text-to-image via the hiapi API: curl, Python, and a Working Request

How to Use the qwen-image-3.0 API: curl, Python, and a Working Request

How to Use the qwen-image-3.0 API: curl, Python, and a Working Request

How to Use qwen-image-3.0-pro via the hiapi API: curl, Python, and a Working Request

How to Use qwen-image-3.0-pro via the hiapi API: curl, Python, and a Working Request

Start generating