HiAPI
Blog

Tutorial

So verwendest du imagen4-ultra über die HiAPI API: curl- und Python-Beispiele

Eine vollständige Request-Praxisübung für hochwertige Text-zu-Bild-Generierung auf HiAPI

Oct 31, 2026
博客封面图:淡蓝底上多层半透明玻璃平面叠错排列,折射出克制的冷蓝色带。

Was imagen4-ultra auf HiAPI für dich bietet

imagen4-ultra ist das hochwertige Text-zu-Bild-Modell von HiAPI: Du sendest einen Prompt und erhältst ein generiertes Bild. Der wirklich praktische Punkt für Entwickler ist, dass es wie alle anderen Modelle der Plattform hinter der einheitlichen HiAPI-Schnittstelle läuft. Daher lassen sich die Authentifizierung, die Request-Struktur und das Muster zur Aufgabenverarbeitung, die du hier lernst, direkt auf andere Endpunkte übertragen.

Dieses Tutorial ist eine lauffähige Praxisübung und keine bloße Parameterauflistung. Nach dem Lesen hast du:

  • einen direkt kopierbaren curl-Request zum Einreichen einer Text-zu-Bild-Aufgabe,
  • einen kleinen Python-Client, der denselben Request nachbildet,
  • ein klares Verständnis dafür, wie Seitenverhältnis und andere Optionen die Ausgabe beeinflussen,
  • und eine Polling-Schleife, die auf den Abschluss der Aufgabe wartet und das Bild auf der Festplatte speichert.

Eine Erwartung vorweg: Die Bilderzeugung ist nicht sofort. imagen4-ultra arbeitet asynchron – du reichst eine Aufgabe ein, erhältst eine Aufgabenkennung und pollst dann, bis das Rendering abgeschlossen ist. Wenn du andere asynchrone Endpunkte von HiAPI verwendet hast, wird dir dieser Ablauf vertraut vorkommen; falls nicht, deckt das Polling-Kapitel den vollständigen Lebenszyklus ab.

Wir bleiben durchgehend im Rahmen der HiAPI-eigenen API: kein herstellerspezifisches SDK, keine Drittanbieter-Konsole. Eine Basis-URL, ein Schlüssel, ein Request-Format.

Bevor du den ersten Request sendest

Bevor der erste Aufruf erfolgreich sein kann, brauchst du drei Dinge.

1. Einen API-Schlüssel

Erzeuge den Schlüssel in der Konsole deines HiAPI-Kontos. Behandle ihn wie ein Passwort: Speichere ihn in einer Umgebungsvariable und füge ihn nicht direkt in eine Quelldatei ein.

export HIAPI_API_KEY="your-key-here"

2. Die Basis-URL

Alle HiAPI-Requests gehen an denselben API-Host, der in der Plattformdokumentation beschrieben ist. Lege ihn im Code an einer einzigen Stelle ab, damit du ihn nicht an mehreren Stellen fest verdrahtest:

export HIAPI_BASE_URL="https://api.hiapi.ai"

Falls dein Konto oder deine Region einen anderen Host verwendet, nutze den in der Konsole angezeigten Wert – die Request-Pfade unten bleiben unverändert.

3. Wie die Authentifizierungsinformationen übergeben werden

HiAPI verwendet ein Bearer-Token im Authorization-Header. Jeder Request – ob Einreichen oder Polling – trägt dieselben zwei Header:

Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json

Das ist alles zur Authentifizierung. Kein Signaturschritt für Requests, kein Token-Austausch pro Aufruf. Sobald du Header setzen kannst, kannst du diese API aufrufen.

Eine kurze Grundprüfung vor dem Weitergehen: Stelle sicher, dass dein Schlüssel in derselben Shell-Sitzung exportiert wurde, in der du curl ausführen wirst. Ein beträchtlicher Anteil der „401 Unauthorized“-Meldungen läuft letztlich darauf hinaus, dass der Schlüssel in einem Terminal-Tab exportiert und in einem anderen verwendet wurde.

Im Folgenden gehen wir stets davon aus, dass die Modellkennung imagen4-ultra lautet. Wenn du den exakten String bestätigen möchtest, den dein Konto bereitstellt, sieh dir die Modellliste in der Dokumentation an.

Der lauffähige curl-Request

Das Folgende ist ein vollständiger Einreichungs-Request. Er sendet den Prompt, setzt das Ausgabeseitenverhältnis und fordert ein einzelnes Bild an.

curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "imagen4-ultra",
    "prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
    "aspect_ratio": "16:9",
    "n": 1
  }'

Feldweises Durchgehen des Request-Bodys:

  • model – die Modellkennung, die du aufrufst. Sie bestimmt das Routing des Requests; ohne sie kann die API nicht wissen, welches Modell ausgeführt werden soll.
  • prompt – die natürlichsprachliche Beschreibung des Bildes. Dies ist der wichtigste Hebel für die Ausgabequalität. Sei konkret in Bezug auf Motiv, Beleuchtung, Stil und Komposition; vage Prompts erzeugen nur vage Bilder.
  • aspect_ratio – die Form der Ausgabefläche, angegeben als Breite:Höhe. Wird weiter unten ausführlich erläutert.
  • n – wie viele Bilder mit dieser Einreichung generiert werden sollen. Halte es während des Testens auf 1, damit die Kosten pro Lauf leicht nachvollziehbar bleiben.

Je nach Endpunktkonfiguration enthält die Antwort entweder das fertige Bild oder – bei dieser Art von Modell häufiger – ein Aufgabenobjekt mit einer Kennung und einem Statusfeld. Erfasse diese Kennung; das Polling-Kapitel hängt davon ab.

# Typical structure of the submission response
{
  "id": "job_abc123",
  "status": "queued"
}

Verarbeite die Antwort mit einem JSON-Formatierer (falls verfügbar, | jq .), damit du die Feldnamen anhand der Antwort deines Kontos lesen kannst, statt eine einzige Zeile entziffern zu müssen.

Derselbe Request in Python

Die Python-Version ist eine zeilenweise Entsprechung – dieselbe URL, dieselben Header, derselbe Request-Body. Mit requests wird die Zuordnung offensichtlich:

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ.get("HIAPI_BASE_URL", "https://api.hiapi.ai")

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

payload = {
    "model": "imagen4-ultra",
    "prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
    "aspect_ratio": "16:9",
    "n": 1,
}

response = requests.post(
    f"{BASE_URL}/v1/images/generations",
    headers=headers,
    json=payload,
    timeout=30,
)
response.raise_for_status()
job = response.json()
print(job["id"], job["status"])

Wenn du diesen Code in einen echten Dienst übernimmst, lohnt es sich, einige Punkte beizubehalten:

  • Den Schlüssel aus einer Umgebungsvariable lesen, niemals aus einem Literal in einer Datei. Die Schreibweise os.environ[...] schlägt bei fehlender Variable eindeutig fehl, und genau das willst du.
  • Einen expliziten Timeout für den Einreichungsaufruf setzen. Die Aufgabe selbst läuft asynchron, daher sollte der HTTP-Request schnell zurückkehren; eine Obergrenze von 30 Sekunden fängt Netzwerkprobleme ab, statt das Programm hängen zu lassen.
  • raise_for_status() aufrufen, bevor du auf JSON zugreifst. Der Body einer 4xx-Antwort hat nicht die erwartete Struktur; früh zu scheitern liefert einen klareren Traceback als ein KeyError drei Zeilen später.
  • Eine requests.Session wiederverwenden, wenn du viele Aufgaben einreichst – Connection-Pooling ist wichtiger, als es scheint.

Wenn du httpx oder aiohttp bevorzugst, ist die Umstellung mechanisch: dasselbe Headers-Dictionary, derselbe JSON-Request-Body, derselbe Pfad. Der Request selbst ist unabhängig von der HTTP-Bibliothek.

Seitenverhältnis und Request-Optionen

Das Seitenverhältnis ist die Option, die du am häufigsten anpasst, weil sie sowohl die Komposition als auch die Ausgabemaße für das nachgelagerte Layout verändert.

Das Seitenverhältnis wird im Request-Body als String im Format "width:height" übergeben – "1:1", "16:9", "9:16", "4:3", "3:2" und so weiter. Wähle das Verhältnis passend zum späteren Verwendungszweck des Bildes:

  • 1:1 – Avatare, Produktkacheln, quadratisch zugeschnittene Social-Media-Posts.
  • 16:9 / 9:16 – Hero-Banner, Video-Thumbnails, Platzierungen im vertikalen Story-Format.
  • 4:3 / 3:2 – klassische fotografische Kompositionen, Galerie-Layouts.

Setze das Verhältnis bewusst, statt zuerst ein Quadrat zu generieren und dann zuzuschneiden. Zuschneiden verwirft Pixel, die du bereits bezahlt hast, und kann das Motiv aus dem Bild schneiden. Wenn du die endgültige Platzierung kennst, kodiere sie in den Request.

Neben dem Seitenverhältnis sind die im Alltag wichtigen Optionen:

  • prompt – nach wie vor die einflussreichste Eingabe. Iteriere hier, bevor du an irgendeiner anderen Stelle iterierst.
  • n – die Anzahl der Bilder pro Einreichung. Nützlich, wenn du mehrere Varianten zur Auswahl möchtest; halte den Wert beim Erkunden von Prompts niedrig.
  • model – der exakte Bezeichner der Modellvariante. Wenn dein Konto mehrere Bildmodelle bereitstellt, ist dies der Umschalter zwischen ihnen.

Halte dich an die in der Dokumentation des Endpunkts beschriebenen Parameter und rate keine Namen. Unbekannte Felder sind eine häufige Ursache für 400-Antworten, und falsch geschriebene Optionen fallen in großen Request-Bodys leicht nicht auf. Wenn du unsicher bist, sende zuerst einen minimalen Request-Body – model, prompt, aspect_ratio – bestätige, dass er funktioniert, und füge dann jeweils eine Option hinzu.

Asynchrone Aufgaben pollen und Ergebnisse herunterladen

Die Bilderzeugung braucht Zeit, daher liefert der Einreichungsaufruf eine Aufgabe und kein Bild. Der Lebenszyklus ist: einreichen → Status pollen → Ausgabe herunterladen.

Schritt 1: Einreichen und die Aufgaben-ID erfassen

Verwende den vorherigen Request wieder und entnimm die id aus der Antwort:

job = response.json()
job_id = job["id"]

Schritt 2: Pollen, bis die Aufgabe einen Endzustand erreicht

Poll den Status-Endpunkt mit denselben Authentifizierungs-Headern und lege zwischen den Versuchen eine Pause ein. Verwende schrittweises Backoff, um die API nicht übermäßig zu belasten:

import time

def wait_for_job(job_id, headers, base_url, timeout=300):
    deadline = time.time() + timeout
    delay = 2
    while time.time() < deadline:
        r = requests.get(
            f"{base_url}/v1/images/generations/{job_id}",
            headers=headers,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()
        status = data["status"]
        if status == "succeeded":
            return data
        if status == "failed":
            raise RuntimeError(f"job failed: {data}")
        time.sleep(delay)
        delay = min(delay * 2, 15)
    raise TimeoutError(f"job {job_id} not finished within {timeout}s")

Wichtige Details: eine harte Frist, eine Obergrenze für das Backoff-Intervall und ein expliziter Zweig für Fehlerzustände, damit problematische Aufgaben als Ausnahme sichtbar werden, statt einfach hängen zu bleiben.

Schritt 3: Das Bild herunterladen

Die Antwort der abgeschlossenen Aufgabe enthält den Ausgabeort – eine URL oder eine äquivalente Artefakt-Referenz. Rufe sie ab und schreibe die Bytes auf die Festplatte:

result = wait_for_job(job_id, headers, BASE_URL)
image_url = result["output"][0]["url"]

img = requests.get(image_url, timeout=60)
img.raise_for_status()
with open("lighthouse.png", "wb") as f:
    f.write(img.content)

Zwei Gewohnheiten, die die meisten Überraschungen im Produktivbetrieb vermeiden: immer im Binärmodus schreiben ("wb"), niemals im Textmodus; und die Download-URL als temporär behandeln – speichere die Datei sofort in deinem eigenen Speicher, statt darauf zu vertrauen, dass der Link unbegrenzt gültig bleibt.

Häufige Fehler und ihre Behebung

Die meisten Fehlschläge lassen sich in einige wenige Kategorien einordnen. Im Folgenden findest du für jede Kategorie die Symptome und die Lösung.

401 Unauthorized

Der Schlüssel fehlt, ist falsch formatiert oder für den Prozess, der den Request ausführt, nicht sichtbar.

  • Prüfe, ob der Header exakt Authorization: Bearer <key> lautet – das Wort Bearer, ein Leerzeichen und dann der Schlüssel.
  • Stelle sicher, dass die Umgebungsvariable in derselben Shell bzw. demselben Prozess gesetzt ist. In Containern und CI werden Variablen, die du in deiner lokalen Shell exportiert hast, nicht mit dem Code übertragen.
  • Wenn du den Schlüssel kürzlich rotiert hast, stelle sicher, dass der alte Schlüssel nicht noch irgendwo zwischengespeichert ist.

400 Bad Request

Meist ein Problem des Request-Bodys.

  • Unbekannte oder falsch geschriebene Feldnamen – halte dich an die in der Dokumentation beschriebenen Parameter.
  • Ein aspect_ratio-Wert, den der Endpunkt nicht akzeptiert – verwende die in der Dokumentation beschriebene Form width:height.
  • n liegt außerhalb des erlaubten Bereichs.
  • Fehlerhaftes JSON – etwa ein überflüssiges Komma oder ein nicht maskiertes Anführungszeichen innerhalb des Prompt-Strings. Wenn du das vermutest, gib den Request-Body vor dem Senden formatiert aus und prüfe ihn.

404 bei der Statusabfrage oder beim Download-Schritt

Die Aufgaben-ID ist falsch, oder der Pfad, den du pollst, passt nicht zu dem Endpunkt, den du zum Einreichen verwendet hast. Protokolliere bei der ersten Integration die Einreichungsantwort vollständig und vergleiche die ID Zeichen für Zeichen.

Polling-Timeout

Wenn wait_for_job die Frist erreicht:

  • Stelle sicher, dass du den richtigen Statuswert prüfst; ein Endzustand, den du nicht erkennst, sieht wie ein Hänger aus.
  • Bei großen, komplexen Renderings erhöhe den Gesamt-Timeout, statt das Polling-Intervall zu verkürzen.
  • Protokolliere während der Integration jede Statusantwort, damit du siehst, wie lange Aufgaben mit deinen Prompt-Kombinationen tatsächlich brauchen.

Aufgabenstatus failed

Lies den Fehler-Response-Body, den die API zurückgibt – er ist aus einem Grund vorhanden. Fehlgeschlagene Aufgaben liegen meist auf der Prompt- oder Parameterseite; die Korrektur gehört in den Request, nicht in den Polling-Code.

Wo etwas unklar ist, ist die HiAPI-Dokumentation zu diesem Modell die maßgebliche Quelle für Feldnamen und zulässige Werte. Validiere jeweils nur eine Änderung und bewahre einen bekanntermaßen funktionierenden Request als Referenz für die nächste Integration auf.

Ä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