HiAPI
Blog

Tutorial

So verwenden Sie flux-2-klein-9b/image-to-image über die hiapi API: curl, Python und lauffähige Anfragen

Jul 30, 2026
So verwenden Sie flux-2-klein-9b/image-to-image über die hiapi API: curl, Python und lauffähige Anfragen

Dieses Tutorial zeigt, wie Sie den image-to-image-Modus von flux-2-klein-9b über die einheitliche Task-API von hiapi aufrufen: die genaue Anfragestruktur, einen lauffähigen curl-Befehl, ein Python-Skript, das direkt ins Backend übernommen werden kann, sowie eine Schema-Eigenheit, über die Sie stolpern, wenn Sie von anderen Modellen der Plattform migrieren.

Nach dem Lesen verfügen Sie über ein Skript, das eine einzelne Referenzbild-URL und einen Bearbeitungsprompt entgegennimmt und eine herunterladbare URL des generierten Bildes zurückgibt.

Was Sie benötigen

  • Ein hiapi-Konto und einen API key. Erhältlich in der hiapi-Konsole.
  • Genau ein Referenzbild, das unter einer öffentlichen HTTPS-URL gehostet wird. Anders als einige image-to-image-Modelle der Plattform, die mehrere Referenzbilder akzeptieren, ist das image_urls-Array von flux-2-klein-9b auf einen Eintrag begrenzt – Details siehe unten.
  • Einen Textprompt, der die Bearbeitung oder Transformation beschreibt.

Alle Anfragen gehen an den einheitlichen Task-Endpunkt, der Schlüssel wird im Authorization-Header übergeben:

POST https://api.hiapi.ai/v1/tasks
Authorization: Bearer sk-<your-key>
Content-Type: application/json

Anfragestruktur (und ein leicht zu übersehendes Feld)

Die Modell-ID lautet flux-2-klein-9b/image-to-image – übergeben Sie sie unverändert genau so, wie sie in /v1/models aufgeführt ist. Das input-Schema ist streng:

Feld Typ Erforderlich Beschreibung
prompt string Ja Die Bearbeitungsanweisung.
image_urls string[] Ja Genau eine Referenzbild-URL – minItems und maxItems sind beide 1.
aspect_ratio string Nein Einer der Werte: 1:1, 4:3, 3:4, 16:9, 9:16.
seed integer Nein Festlegen für reproduzierbare Ergebnisse.
output_format string Nein Einer der Werte: jpeg, png, webp.

Bevor Sie Code schreiben, sollten Sie zwei Dinge wissen:

  1. image_urls akzeptiert nur eine URL, keinen Bereich.Wenn Sie gemeinsamen Übermittlungscode um ein Modell herum gebaut haben, das 1–14 Referenzbilder akzeptiert, wird das Senden von zwei URLs hier abgelehnt – maxItems: got 2, want 1. Dieses Modell führt die Bearbeitung eines einzelnen Bildes durch, keine Fusion mehrerer Referenzbilder.
  2. Zusätzliche Felder werden abgelehnt, nicht ignoriert.resolution, size, n, strength, image_size und num_images – alle bei anderen Bildmodellen der Plattform üblich – liefern hier alle 400 INVALID_REQUEST: additional properties '<field>' not allowed. Wiederverwenden Sie nicht das Payload eines anderen Modells, ohne das Schema dieses Modells zu prüfen.

Minimales lauffähiges Beispiel: curl

Task erstellen:

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-2-klein-9b/image-to-image",
    "input": {
      "prompt": "Change the jacket to charcoal grey leather, keep the pose and background unchanged",
      "image_urls": ["https://your-cdn.example.com/subject.png"],
      "aspect_ratio": "3:4",
      "output_format": "png"
    }
  }'

Nach erfolgreicher Übermittlung wird eine Task-ID in data zurückgegeben:

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

Ergebnis abfragen (Polling):

curl https://api.hiapi.ai/v1/tasks/tk-hiapi-... \
  -H "Authorization: Bearer sk-<your-key>"

Während der Ausführung durchläuft data.status nacheinander queued → handling → archiving. Nach Abschluss springt es auf "success" und das Bild erscheint in data.output:

{
  "code": 200,
  "data": {
    "status": "success",
    "output": [{"url": "https://.../result.png", "expireAt": "..."}]
  }
}

Ausgabe-URLs sind kurzlebig (beachten Sie expireAt). Laden Sie die Bytes sofort herunter und speichern Sie sie selbst – niemals hotlinken oder die Original-URL persistieren.

Produktionsreifes Python: Senden, Polling, Herunterladen

import time
import requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}


def edit_image(prompt: str, image_url: str,
               aspect_ratio: str = "1:1", output_format: str = "png") -> bytes:
    # 1. Task erstellen – image_urls dieses Modells akzeptiert genau eine URL
    resp = requests.post(API_BASE, headers=HEADERS, json={
        "model": "flux-2-klein-9b/image-to-image",
        "input": {
            "prompt": prompt,
            "image_urls": [image_url],
            "aspect_ratio": aspect_ratio,
            "output_format": output_format,
        },
    }, timeout=60)
    body = resp.json()
    if resp.status_code != 200 or not (body.get("data") or {}).get("taskId"):
        raise RuntimeError(f"create failed [{resp.status_code}]: {body}")
    task_id = body["data"]["taskId"]

    # 2. Polling bis zum Endzustand
    deadline = time.time() + 600
    while time.time() < deadline:
        task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS,
                            timeout=30).json().get("data") or {}
        if task.get("status") == "success":
            outputs = task.get("output") or []
            if not outputs or not outputs[0].get("url"):
                raise RuntimeError(f"task {task_id} succeeded but returned no output URL")
            # 3. Sofort herunterladen – URLs verfallen
            img = requests.get(outputs[0]["url"], timeout=120)
            img.raise_for_status()
            return img.content
        if task.get("status") == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(5)
    raise TimeoutError(f"task {task_id} still running after 600s")


if __name__ == "__main__":
    png = edit_image(
        "Change the jacket to charcoal grey leather, keep the pose and background unchanged",
        "https://your-cdn.example.com/subject.png",
        aspect_ratio="3:4",
    )
    with open("edited.png", "wb") as f:
        f.write(png)
    print(f"saved edited.png ({len(png)} bytes)")

Reproduzierbare Bearbeitungen mit seed

Übergeben Sie einen ganzzahligen seed, verwendet das Modell ihn für diese Generierung wieder – nützlich, wenn Sie alles andere unverändert lassen und die Formulierung des Prompts A/B-testen möchten:

{
  "model": "flux-2-klein-9b/image-to-image",
  "input": {
    "prompt": "Change the jacket to charcoal grey leather, keep the pose and background unchanged",
    "image_urls": ["https://your-cdn.example.com/subject.png"],
    "seed": 42
  }
}

Lassen Sie ihn weg, wählt das Modell bei jedem Aufruf einen zufälligen seed – genau das, was normaler Produktionsverkehr möchte. Wenn Sie anders aussehende Ergebnisse benötigen, ändern Sie den Prompt, nicht den seed.

Callback statt Polling

Für Skripte und Worker-Queues ist Polling in Ordnung. Für ein Web-Backend registrieren Sie beim Erstellen des Tasks einen Callback, damit hiapi den Endzustand an Sie pusht – das callback-Objekt liegt auf oberster Ebene der Anfrage, gleichrangig mit model:

{
  "model": "flux-2-klein-9b/image-to-image",
  "input": { "...": "..." },
  "callback": {
    "url": "https://your-app.example.com/hooks/hiapi",
    "when": "final"
  }
}

Mit "when": "final" erhalten Sie genau ein POST, wenn der Task den Erfolgs- oder Fehlerzustand erreicht. Für den Handler gelten zwei Regeln:

  • Machen Sie ihn idempotent.Schlüsseln Sie Ihre Verarbeitungslogik auf die Task-ID, damit erneut zugestellte Webhooks nicht doppelt verarbeitet werden. Speichern Sie die Task-ID bei der Übermittlung und behandeln Sie den Callback als „abholen und abschließen“ und nicht als einzige Wahrheitsquelle.
  • Behalten Sie einen Abgleichpfad.Wenn Ihr Endpunkt beim Auslösen des Callbacks nicht verfügbar ist, können Sie durch regelmäßiges Scannen ungelöster IDs und GET /v1/tasks/<id> alles Verpasste nachholen.

Wenn Ihr Callback scheinbar nie ankommt, prüfen Sie der Reihe nach warum Ihr hiapi-Task-Callback nicht ausgelöst wird – der Artikel deckt die häufigen Fehlermuster nach Wahrscheinlichkeit geordnet ab.

Fehlerbehandlung: drei kritische Fehlerszenarien

401 permission_denied beim Erstellen – Ihr Schlüssel kann dieses Modell nicht verwenden. Der Antwortbody sieht so aus:

{"error": {"code": "permission_denied", "message": "...", "request_id": "...", "type": "hiapi_error"}}

Wenn Sie darauf stoßen, prüfen Sie API key ungültig oder die Modellberechtigungen des Schlüssels in der Konsole.

400 INVALID_REQUEST beim Erstellen – Ihr input passt nicht zum Schema dieses Modells. Die Meldung benennt das fehlerhafte Feld direkt (z. B. <root>: additional properties 'resolution' not allowed oder image_urls: maxItems: got 2, want 1). Dies sind dauerhafte Fehler – das erneute Senden desselben Payloads wird für immer fehlschlagen; korrigieren Sie das Feld und senden Sie erneut.

Task liefert status: "fail" – Erstellung erfolgreich, aber die Generierung fehlgeschlagen (vom Backend nicht abrufbare Referenz-URL, Inhaltsrichtlinien, Upstream-Kapazität). error.code und error.message des Tasks geben an, welcher Fall vorliegt. Anders als bei 400 sind einige davon vorübergehend und einen Wiederholungsversuch mit Backoff wert.

Ebenfalls gut zu wissen: Ein GET auf eine nicht existierende oder abgelaufene Task-ID liefert 404 task not found – dies sollte in Abgleich-Scans als Endzustand behandelt werden, nicht als „läuft noch“.

Wo es weitergeht

Häufige Fragen

Kann ich mehrere Referenzbilder an flux-2-klein-9b image-to-image übergeben? Nein. minItems und maxItems von image_urls sind beide auf 1 gesetzt – genau eine URL, nicht mehr und nicht weniger. Wenn Sie eine Fusion mehrerer Referenzbilder benötigen, sehen Sie sich Modelle an, deren Schema einen größeren Bereich dokumentiert, z. B. seedream-5.0-lite.

Warum erhalte ich „additional properties 'resolution' not allowed“? Das input-Schema der Task-API ist modellspezifisch. flux-2-klein-9b/image-to-image akzeptiert die Felder resolution oder size überhaupt nicht – die Ausgabegröße folgt dem Eingabebild und aspect_ratio. Entfernen Sie alle Größenfelder, die Sie aus dem Payload eines anderen Modells mitgebracht haben.

Kann ich das Referenzbild als base64 statt als URL senden? Das Schema dieses Modells akzeptiert image_urls – ein Array von URLs. Hosten Sie das Bild unter einer erreichbaren HTTPS-URL (jeder CDN, Object-Storage-Bucket oder vortsignierte URL ist möglich) und übergeben Sie diese URL.

Was steuert seed konkret? Mit demselben seed, demselben prompt und demselben Referenzbild wird dieselbe Generierung reproduziert – nützlich für kontrollierte A/B-Tests von Prompts. Lassen Sie ihn im normalen Verkehr weg, damit jeder Aufruf seinen eigenen zufälligen seed erhält.

Funktioniert derselbe Code für flux-2-klein-9b text-to-image? Endpunkt und Ablauf sind gleich, aber text-to-image hat sein eigenes input-Schema (ohne image_urls). Ersetzen Sie die Modell-ID durch flux-2-klein-9b/text-to-image und entfernen Sie das Referenzbild – und verifizieren Sie dann mit einem Testaufruf, da die Pflichtfelder je nach Modus variieren.

Wie viel kostet jedes Bild? Die Abrechnung erfolgt nach Nutzung pro Generierung. Die aktuellen Tarife finden Sie auf der Preisseite.

Ähnliche Artikel

Alle Artikel ansehen →

Starte mit persistenten KI-Artefakten

Hol dir deinen API-Key und rufe Bild-, Video- und Audiomodelle über eine einzige task-basierte API auf.

API-Dokumentation lesen