HiAPI
Blog

Tutorial

So rufen Sie die Imagen 4 API über HiAPI auf: curl- und Python-Beispiele

Oct 31, 2026
博客封面图:淡灰紫色块与墨黑色块以一条笔直硬边相接,交界处一道细紫缝,构图简洁平静。

Was der Imagen 4 Endpoint Ihnen bietet

Wenn Sie bereits einen Prompt haben und ein Bild erhalten möchten, ohne ein Abrechnungskonto zu registrieren, eine Queue einzurichten oder einen Bucket bei einem Anbieter anzulegen, den Sie noch nie verwendet haben, ist das Modell Google-Imagen4 auf HiAPI ein sinnvoller Ausgangspunkt. Sie senden einen Text-Prompt an einen einzelnen HTTP-Endpoint, authentifizieren sich mit einem API-Schlüssel und erhalten dann eine Referenz auf das generierte Bild (oder eine abfragbare Aufgabe). Alles andere – Modell-Hosting, Kapazität, anbieterseitige Wiederholungen – ist abstrahiert.

Der Text-zu-Bild-Aufruf über diesen Endpoint deckt drei Dinge ab, die Sie in der Praxis interessieren werden:

  • Vom Prompt zum Bild. Der Prompt ist die Haupteingabe. Je nach Konfiguration der Anfrage gibt das Modell ein oder mehrere Bilder zurück.
  • Kontrolle der Ausgabeform. Sie können das Seitenverhältnis (quadratisch, quer, hochkant) bereits bei der Anfrage angeben, statt nachträglich zuzuschneiden. Das ist wichtiger, als es klingt: Das Zuschneiden eines fertigen Bildes verwirft die Komposition, die das Modell bereits geplant hatte.
  • Asynchrone Ausführung. Längere Generierungen werden als Aufgabe abgewickelt. Sie reichen ein, fragen den Status ab und holen dann das Ergebnis. Kurze Aufrufe können schnell zurückkehren, aber Sie sollten Ihren Client so schreiben, dass jeder Aufruf asynchron ist – denn das ist der Ablauf, der Produktionsverkehr standhält.

Der Rest dieses Tutorials baut dieselbe Anfrage auf drei Arten auf: einen rohen curl-Aufruf, den Sie direkt ins Terminal einfügen können, einen äquivalenten Python-Client und dann die Teile, die Sie für Seitenverhältnisse, Polling, Persistenz und Fehlerbehandlung benötigen. Wenn Sie mit einer einzigen Shell-Befehl ein Bild erzeugen möchten, ist das gut geeignet. Wenn Sie feinkörnige Kontrolle über Inpainting-Masken oder Trainingsschleifen benötigen, ist es möglicherweise nicht das Richtige.

Zwei Voraussetzungen vor dem Start: Sie besitzen einen HiAPI API-Schlüssel, und Ihre Code-Umgebung kann ausgehende HTTPS-Anfragen senden. Darüber hinaus gibt es keine weiteren Anforderungen – die Installation eines SDK ist nicht zwingend, die Python-Beispiele unten verwenden jedoch requests.

Ihre erste Anfrage mit curl senden

Der schnellste Weg, um zu bestätigen, dass der Schlüssel funktioniert, ist ein curl-Aufruf. Der Endpoint akzeptiert einen JSON-Anfragekörper, daher benötigen Sie zwei Header: Content-Type für den Körper und Authorization für den Schlüssel. Lesen Sie den Schlüssel aus einer Umgebungsvariable, statt ihn direkt in den Befehl einzufügen, damit er nicht in Ihrer Shell-Historie verbleibt.

export HIAPI_API_KEY="your-key-here"

curl -sS -X POST "https://api.hiapi.ai/v1/images/generations" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -d '{
    "model": "google-imagen-4",
    "prompt": "a weathered lighthouse on a basalt cliff, morning fog, wide shot",
    "n": 1,
    "aspect_ratio": "16:9"
  }'

Ein paar Dinge in diesem Anfragekörper sind beachtenswert:

  • model wählt Google-Imagen4. Schreiben Sie es explizit, auch wenn der Dienst einen Standardwert hat – so bleibt Ihr Code auch in einem Jahr noch lesbar.
  • prompt ist die einzige erforderliche kreative Eingabe. Schreiben Sie ihn, wie Sie einem Fotografen eine Aufnahme beschreiben würden: Motiv, Umgebung, Licht, Bildausschnitt.
  • n steuert, wie viele Bilder Sie erhalten möchten. Beginnen Sie mit einem, während Sie die Antwortstruktur korrekt einrichten; erhöhen Sie den Wert, sobald Sie Ihrer Pipeline vertrauen.
  • aspect_ratio wird weiter unten ausführlich behandelt. Wenn Sie es weglassen, wird auf den Dienststandard zurückgegriffen.

Eine erfolgreiche Antwort gibt ein JSON-Objekt zurück. Der Teil, der Sie interessiert, ist die Liste der Bildeinträge; jeder Eintrag enthält eine herunterladbare Referenz oder eine URL, die Sie an das Frontend weitergeben können. Wenn Sie mehrere Bilder angefordert haben, erhalten Sie mehrere Einträge in der Reihenfolge der Anfrage. Wenn die Generierung lange genug dauert und in eine Warteschlange gestellt wird, liefert die Antwort stattdessen eine Kennung und einen abfragbaren Status – dieser Ablauf wird im entsprechenden Abschnitt unten beschrieben.

Wenn Sie eine 4xx erhalten, prüfen Sie zuerst die beiden Header: Ein fehlendes Bearer -Präfix oder ein Leerzeichen am Ende des Schlüssels sind die häufigsten Ursachen für fehlgeschlagene erste Aufrufe. Verwenden Sie beim Debuggen -i, um die Statuszeile und den Fehlerantwortkörper anzuzeigen.

Dieselbe Anfrage mit Python senden

In einem Skript kapseln Sie den Aufruf in eine kleine Funktion, damit der restliche Code niemals rohes HTTP anfassen muss. Die Funktion sollte den Prompt und optionale Parameter entgegennehmen, den Anfragekörper erstellen, die Anfrage senden und das geparste JSON zurückgeben.

import os
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def generate_image(prompt: str, aspect_ratio: str = "1:1", n: int = 1) -> dict:
    response = requests.post(
        f"{HIAPI_BASE}/images/generations",
        headers={
            "Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
            "Content-Type": "application/json",
        },
        json={
            "model": "google-imagen-4",
            "prompt": prompt,
            "n": n,
            "aspect_ratio": aspect_ratio,
        },
        timeout=120,
    )
    response.raise_for_status()
    return response.json()


if __name__ == "__main__":
    result = generate_image(
        "a weathered lighthouse on a basalt cliff, morning fog, wide shot",
        aspect_ratio="16:9",
    )
    print(result)

Drei Designentscheidungen in diesem Code sollten Sie beim Anpassen beibehalten:

Explizites Timeout. requests hat kein Standard-Timeout, was bedeutet, dass eine hängende Verbindung einen Worker unbegrenzt blockieren kann. Wählen Sie einen Wert, der über Ihrer langsamsten erwarteten Generierungszeit liegt, und lassen Sie ihn explizit fehlschlagen.

raise_for_status() vor dem Parsen aufrufen. Fehlerantworten haben nicht immer dasselbe Schema wie erfolgreiche Antworten. Prüfen Sie zuerst den HTTP-Status, bevor Sie den Antwortkörper anfassen.

Kleine, parametrisierte Funktion. Wenn Sie Polling und Download hinzufügen, bleibt diese Funktion der einzige Einstiegspunkt für die Übermittlung, wobei die Lebenszykluslogik daneben liegt und nicht darin verwickelt ist.

Das geparste Ergebnis enthält dieselben Informationen wie die curl-Ausgabe. Für synchrone Antworten durchlaufen Sie die Bildeinträge und extrahieren die URL. Für asynchrone Antworten extrahieren Sie die Aufgabenkennung und übergeben sie an die Polling-Funktion. Ihr Code sollte je nach erhaltener Form verzweigen und nicht nur eine Form annehmen.

Seitenverhältnis und Ausgabe steuern

Das Seitenverhältnis ist der Parameter, den Sie am häufigsten anpassen, und es lohnt sich, ihn richtig zu setzen, statt nachträglich zuzuschneiden. Wenn Sie ein quadratisches Bild anfordern und daraus einen 16:9-Bereich ausschneiden, verlieren Sie oben und unten die vom Modell bewusst gestaltete Komposition. Wenn Sie vorab 16:9 anfordern, kann das Modell die Aufnahme für dieses Format planen.

Übergeben Sie es zusammen mit dem Prompt im Anfragekörper:

result = generate_image(
    "a sprawling night market, neon signs, steam from food stalls",
    aspect_ratio="16:9",
    n=2,
)

Querformate eignen sich für Hero-Banner, Vorschaubilder breiter Karten und Produktfotografie; Hochformate für Mobile-First-Karten, Poster und Porträts; quadratische Formate für Avatare und Social-Media-Beiträge, bei denen der Zuschnitt unvorhersehbar ist. Entscheiden Sie danach, wo das Bild letztendlich platziert wird, und nicht danach, ob es isoliert gut aussieht.

Was sich in der Antwort ändert, wenn Sie das Verhältnis ändern: die Pixelabmessungen der zurückgegebenen Bilder. Anzahl, Reihenfolge und Download-Ablauf der Einträge bleiben gleich, sodass Ihr nachgelagerter Code nicht je nach Verhältnis verzweigen muss. Wenn Ihre UI Platz reserviert, bevor das Bild geladen wird, lesen Sie die Abmessungen aus der Antwort und setzen Sie sie auf das Element, statt Größen fest zu codieren.

Zwei weitere Ausgabestellschrauben sollten Sie kennen:

  • Bildanzahl (n). Mehr Bilder pro Anfrage bedeuten mehr Auswahl, aber auch mehr Token für einen möglicherweise falsch formulierten Prompt. Fordern Sie beim Iterieren der Prompt-Formulierung nur ein Bild an; fordern Sie erst in Batches an, wenn der Prompt stabil ist.
  • Prompt-Formulierung für die Bildkomposition. Das Verhältnis bestimmt das Format; der Prompt bestimmt die Komposition innerhalb des Formats. Wörter wie „wide shot“, „close-up“ und „centered“ wirken zusammen mit dem Verhältnisparameter.

Die Abrechnung dieses Endpoints richtet sich nach der Bilderzeugung selbst – prüfen Sie die aktuelle Preisübersicht auf der Website, statt etwas in Ihr Kostenmodell fest zu codieren.

Asynchrone Aufgaben und Polling behandeln

Wenn die Generierung lange genug dauert und in eine Warteschlange gestellt wird, kehrt der Endpoint zurück, bevor das Bild existiert. Sie erhalten ein Aufgaben-Handle, und Ihre Aufgabe ist es, es zu prüfen, bis es einen Endzustand erreicht. Schreiben Sie diesen Ablauf auch dann, wenn heutige Aufrufe schnell zurückkehren – Kapazität, Prompt-Komplexität und Bildanzahl beeinflussen die Latenz, und ein für synchrone Szenarien gebauter Client bricht beim ersten langsamen Request zusammen.

Der Lebenszyklus besteht aus drei Schritten:

  1. Übermitteln. Senden Sie die Generierungsanfrage wie gewohnt. Wenn die Antwort eine Aufgabe ist, extrahieren Sie deren Kennung.
  2. Polling. Rufen Sie den Task-Status-Endpoint in festen Intervallen mit dieser Kennung auf.
  3. Abholen. Sobald der Status Erfolg meldet, lesen Sie die Bildreferenz aus der Ergebnisnutzlast.
import time


def wait_for_job(job_id: str, interval: float = 2.0, max_attempts: int = 60) -> dict:
    for attempt in range(max_attempts):
        response = requests.get(
            f"{HIAPI_BASE}/images/jobs/{job_id}",
            headers={"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"},
            timeout=30,
        )
        response.raise_for_status()
        payload = response.json()

        status = payload.get("status")
        if status == "succeeded":
            return payload
        if status in {"failed", "cancelled"}:
            raise RuntimeError(f"job {job_id} ended with status {status}")

        time.sleep(interval)

    raise TimeoutError(f"job {job_id} did not finish in time")

Die entscheidenden Details, die diesen Code in der Produktion sicher machen:

  • Versuche begrenzen, nicht endlos schleifen. Eine Aufgabe, die niemals abgeschlossen wird, sollte sich als alarmierbarer Timeout-Fehler manifestieren, nicht als ewig hängender Worker. max_attempts multipliziert mit interval ist Ihr tatsächliches Zeitbudget – legen Sie es basierend auf Ihrer langsamsten realistischen Generierungszeit fest.
  • Backoff unter Last. Ein festes Zwei-Sekunden-Intervall ist für interaktive Nutzung in Ordnung. Für Batch-Workloads sollten Sie schrittweise Backoff oder Jitter hinzufügen, damit Wiederholungen vieler Worker nicht in derselben Sekunde synchronisieren.
  • Fehler von Unbekanntem unterscheiden. Nur failed und cancelled sind terminale Fehler. Behandeln Sie jeden anderen Nicht-Erfolgsstatus als „wird noch bearbeitet“ und fragen Sie erneut ab; eine Verzweigung hinzuzufügen, die bei nicht erkannten Status sofort wirft, wird Probleme bereiten, wenn der Dienst neue Status hinzufügt.
  • Übermittlung bei Netzwerkfehlern wiederholen, nicht das Polling. Wenn der Übermittlungsaufruf selbst ein Timeout hat, kann eine Wiederholung doppelte Aufgaben erzeugen. Wenn die API Idempotenzschlüssel unterstützt, geben Sie jeder Übermittlung einen Idempotenzschlüssel; andernfalls deduplizieren Sie auf Ihrer Seite per Prompt-Hash plus Zeitstempel.

Sobald eine Aufgabe Erfolg meldet, hören Sie mit dem Polling auf. Das Ergebnis zu persistieren und das Aufgaben-Handle für Audit-Zwecke aufzubewahren ist günstiger, als weiter nach einem Status zu fragen, den Sie bereits kennen.

Bilder herunterladen und speichern

Die Generierungsantwort gibt Ihnen Referenzen, nicht die Bildbytes. In den meisten Fällen enthält jeder Bildeintrag eine URL, die mit einer normalen GET-Anfrage abgerufen werden kann. Behandeln Sie diese URL als temporäre Adresse: Laden Sie sie zeitnah herunter, validieren Sie sie und speichern Sie die Bytes an einem Ort, den Sie tatsächlich kontrollieren.

import pathlib
import uuid


def download_images(payload: dict, out_dir: str = "images") -> list[pathlib.Path]:
    target = pathlib.Path(out_dir)
    target.mkdir(parents=True, exist_ok=True)

    saved = []
    for entry in payload.get("data", []):
        url = entry["url"]
        resp = requests.get(url, timeout=60)
        resp.raise_for_status()

        content_type = resp.headers.get("Content-Type", "")
        if not content_type.startswith("image/"):
            raise ValueError(f"unexpected content type: {content_type}")

        path = target / f"{uuid.uuid4().hex}.png"
        path.write_bytes(resp.content)
        saved.append(path)

    return saved

Führen Sie einige Prüfungen durch, bevor Sie eine Aufgabe als abgeschlossen betrachten:

  • Inhaltstyp und Größe. In einigen Umgebungen liefert eine Weiterleitung auf eine Fehlerseite 200 und HTML. Verifizieren Sie vor dem Schreiben in den permanenten Speicher, dass Content-Type mit image/ beginnt und die Größe des Antwortkörpers nicht trivial ist.
  • Benennung. Generieren Sie bei jedem Download einen neuen Namen, statt ihn aus dem Prompt abzuleiten. Prompts wiederholen sich, kollidieren und enthalten Zeichen, die das Dateisystem ablehnt.
  • Prompt mit der Datei speichern. Speichern Sie Prompt, Parameter und Aufgabenkennung in Ihrer eigenen Datenbank oder einer Metadatendatei daneben. Nach sechs Monaten kann Ihnen das Bild allein nicht sagen, welche Anfrage es erzeugt hat.
  • In permanenten Speicher verschieben, nicht kopieren. Schreiben Sie zuerst an einen temporären Ort, validieren Sie und verschieben Sie dann in Ihren Bucket oder CDN-gestützten Speicher. Eine halb geschriebene Datei im permanenten Speicher ist schlimmer als eine fehlgeschlagene Aufgabe.

Wenn Ihre Pipeline viele Bilder erzeugt, trennen Sie den Download-Schritt vom Generierungsschritt. Die Generierung ist der teure und ratenbegrenzte Teil; Download-Wiederholungen sind kostengünstig und sollten niemals dazu führen, dass Sie neu generieren.

Häufige Fehler und Debugging-Checkliste

Die meisten Fehler am ersten Tag fallen in einige wenige Kategorien. Prüfen Sie sie in der folgenden Reihenfolge – jede Prüfung ist schneller als die nächste.

Authentifizierungsfehler (401, 403)

Schlüssel falsch, fehlend oder falsch formatiert. Prüfen Sie, ob der Header-Wert genau Bearer plus Schlüssel ist, ohne Zeilenumbruch durch Einfügen, und ob die Umgebungsvariable tatsächlich in der Shell oder dem Prozess exportiert ist, der den Code ausführt. In der Konsole rotierte Schlüssel machen alte Schlüssel sofort ungültig – wenn ein anderer Dienst gerade ausfällt, fragen Sie, ob jemand den Schlüssel rotiert hat.

Parameter abgelehnt (400, 422)

Der Anfragekörper entspricht nicht dem Schema. Häufige Ursachen: falsch geschriebene model-Kennung, ein aspect_ratio-String, der vom Endpoint nicht akzeptiert wird, oder n außerhalb des unterstützten Bereichs. Drucken Sie den Fehlerantwortkörper – er weist oft auf das problematische Feld hin. Vergleichen Sie Ihr JSON mit dem funktionierenden curl-Beispiel, indem Sie Feld für Feld diffen.

Timeouts

Zwei verschiedene Timeouts werden leicht verwechselt. Ein Client-Timeout bedeutet, dass Ihr HTTP-Aufruf aufgegeben hat; die Aufgabe könnte noch laufen. Eine Aufgabe, die nie einen Endzustand erreicht, bedeutet, dass das Polling-Budget zu klein ist oder die Anfrage tatsächlich fehlgeschlagen ist. Setzen Sie das Client-Timeout höher als Ihre langsamste erwartete Generierungszeit und das Polling-Budget noch höher. Wenn während der Übermittlung ein Client-Timeout auftritt, kann eine blinde Wiederholung Arbeit duplizieren – prüfen Sie, ob bereits eine Aufgabe existiert, bevor Sie erneut übermitteln.

Downloads, die erfolgreich aussehen, aber keine sind

Ein 200-Status mit HTML-Antwortkörper oder eine Null-Byte-Datei bedeutet normalerweise, dass die Bild-URL abgelaufen ist oder beim Abrufen die richtigen Zugriffsrechte fehlten. Laden Sie unmittelbar nach erfolgreicher Aufgabe herunter und validieren Sie Inhaltstyp und Größe wie oben beschrieben.

Ratenbegrenzung (429)

Backoff und erneut versuchen, statt die Schleife zu verschärfen. Exponentielles Backoff mit Jitter ist die Standardantwort; begrenzen Sie die Wiederholungen und machen Sie anhaltende Fehler für Ihr Monitoring sichtbar.

Eine Debugging-Gewohnheit, die es wert ist

Protokollieren Sie vier Dinge pro Anfrage: die Modellkennung, den vollständigen Anfragekörper ohne Schlüssel, die Aufgabenkennung (oder den Antwortstatus bei synchronen Aufrufen) und die Dauer. Wenn in der Produktion etwas schiefgeht, können diese vier Felder normalerweise in weniger als einer Minute sagen, ob das Problem in Ihrem Client, Ihren Parametern oder der Queue liegt.

Beginnen Sie mit dem curl-Aufruf, holen Sie zuerst ein Bild, verschieben Sie dann die Logik in einen Python-Client und fügen Sie Polling und Persistenz drumherum hinzu. Dieser Weg hält jeden Fehler klein und zuordenbar.

Ä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