Search

Search HiAPI models, tools, and resources.

Back to blog
Tutorial

How to Use gemini-nano-banana-2.1 via the hiapi API: curl, Python, and a Working Request

hiapinano-bananaimage-generationtutorial

gemini-nano-banana-2.1 is the newest entry in hiapi's Nano Banana image lineup, tuned for fashion photography, furnished interiors, garment changes, and brand visual concepts. It generates images from a text prompt alone, or edits one or more reference photos when you pass them in. This guide covers the exact request schema, working curl and Python examples, and the errors you'll actually hit wiring it up.

What you need

One hiapi API key (sk-...) from your hiapi dashboard. Current per-image pricing is on the pricing page and the gemini-nano-banana-2.1 model page — it scales with output resolution, which matters once you start calling this in a loop.

Like every image model on hiapi, gemini-nano-banana-2.1 runs through the unified async task API: POST /v1/tasks creates a job, then you either poll GET /v1/tasks/{id} or receive a webhook when it's done. There's no synchronous "give me the image now" endpoint.

Minimal working example: text-to-image

Create the task:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-nano-banana-2.1",
    "input": {
      "prompt": "A fashion editorial photograph of a model in an ivory linen blazer on a sunlit white-stucco terrace above the Mediterranean, 50mm lens, soft directional light, cinematic color grade",
      "aspect_ratio": "4:5",
      "resolution": "2K",
      "output_format": "png"
    }
  }'

The response carries the task id at data.taskId:

{"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}

Poll it:

curl -s https://api.hiapi.ai/v1/tasks/YOUR_TASK_ID \
  -H "Authorization: Bearer sk-YOUR_KEY"

Once data.status is "success", the image is at data.output[0].url. Download it immediately — output URLs are signed and carry an expireAt, so persist the bytes, not the link.

prompt is the only required field (model aside). aspect_ratio, resolution, and output_format are all optional. The accepted aspect_ratio values are 1:1, 2:3, 3:2, 1:4, 4:1, 3:4, 4:3, 4:5, 5:4, 1:8, 8:1, 9:16, 16:9, 21:9, auto — send anything else and the API 400s naming the full valid set. resolution accepts 1K, 2K, or 4K; output_format accepts jpg or png. The schema is strict (additionalProperties: false): a typo'd field name 400s immediately with invalid input: <root>: additional properties '<field>' not allowed rather than silently ignoring it.

Resolution isn't just a quality knob here — it changes the price per image, so always set it explicitly instead of relying on the default.

Image-to-image: editing with reference photos

Pass reference image URLs in image_input to switch the same call into editing mode — the request shape is otherwise identical:

import requests, time

payload = {
    "model": "gemini-nano-banana-2.1",
    "input": {
        "prompt": "Change the model's blazer to deep burgundy silk while keeping her pose, the terrace, and the lighting unchanged",
        "image_input": ["https://example.com/your-reference-photo.jpg"],
        "resolution": "2K",
    },
}

resp = requests.post(
    "https://api.hiapi.ai/v1/tasks",
    headers={"Authorization": "Bearer sk-YOUR_KEY"},
    json=payload,
    timeout=30,
)
task_id = resp.json()["data"]["taskId"]

while True:
    status = requests.get(
        f"https://api.hiapi.ai/v1/tasks/{task_id}",
        headers={"Authorization": "Bearer sk-YOUR_KEY"},
        timeout=30,
    ).json()["data"]
    if status["status"] in ("success", "fail"):
        break
    time.sleep(2)

if status["status"] == "success":
    image_url = status["output"][0]["url"]

image_input takes a list of public URLs — hiapi fetches them, it doesn't accept raw base64 or local file paths. If a URL is unreachable or not an image, the task is created (the request shape passes sync validation) but then resolves to status: "fail" with an INVALID_REQUEST error once hiapi actually tries to fetch it, so check data.error on failed tasks rather than assuming a 200 from the create call means the image will land.

Making it production-reliable

  • Prefer a callback over polling on servers: add "callback": {"url": "https://yourapp.com/webhook", "when": "final"} to the request body and skip the polling loop entirely.
  • Task creation isn't idempotent. A retried POST /v1/tasks after a timeout creates a second job and bills twice. Persist the returned taskId and dedupe on your side before retrying.
  • Auth failures are a 401 with error_code: "permission_denied" and a request ID you can hand to support — check for a missing or revoked key here before assuming the model itself is broken.
  • Resolution drives cost, so pin it explicitly in every request rather than trusting a default that might change.

FAQ

Is gemini-nano-banana-2.1 the same model as Nano-Banana-2? No. They're separate model IDs with separate pricing on hiapi — gemini-nano-banana-2.1 is priced per resolution tier ($0.022 / $0.036 / $0.058 for 1K / 2K / 4K), while Nano-Banana-2 has its own tiered pricing. Check the pricing page before assuming they're interchangeable.

What's the difference between image_input and image_urls? image_input is the field name for this model's reference-image mode. Other models in the Nano Banana family (like Nano-Banana-2-Lite) use image_urls instead — mixing the two up is the most common integration mistake when switching between tiers.

Does gemini-nano-banana-2.1 support image-to-image? Yes — the same /v1/tasks call handles both modes; adding image_input is what switches it into editing.

What happens if I send an invalid aspect_ratio? A 400 listing every accepted value, so you can fix it without guessing.

How much does a request cost? It scales with resolution: roughly $0.022 per image at 1K, $0.036 at 2K, and $0.058 at 4K at the time of writing. Confirm current numbers on the pricing page, since per-model pricing can change.

Generate it with HiAPI

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

HiAPI Blog

Related articles

HiAPI

Generate it with HiAPI

Start generating