WERBEPLATZ VERFÜGBAR · PARTNERSCHAFTEN WILLKOMMEN

Integration der Dezgo REST-API in Webanwendungen: Pay-as-You-Go-Architektur für Text-to-Image und Inpainting

365Finds Editorial
11.430 Wiki-Artikel erfasst

365 Wiki mit deiner KI nutzen

Kopiere den Prompt unten, füge ihn in deine gewohnte KI ein und stelle direkt deine Frage.

Vollständigen Skill herunterladen

Probiere es zuerst mit dem Prompt aus. Wenn du 365 Wiki häufig nutzt, installiere den vollständigen 365Wiki Skill, damit du ihn nicht jedes Mal einfügen musst. Ohne bevorzugte KI funktionieren auch die Webversionen von Gemini oder Microsoft Copilot.

Entwickler und kleine Teams, die generative Bildfunktionen oder Inpainting in Webanwendungen einbetten möchten, stehen häufig vor einem kostspieligen Architektur-Dilemma. Auf der einen Seite verursacht das Self-Hosting von Open-Source-Diffusionsmodellen auf Cloud-GPUs (wie AWS EC2 G5 oder RunPod) erhebliche Betriebskosten: CUDA-Treiberaktualisierungen, vLLM/Diffusers-Wartung, Kaltstart-Latenzen und feste Leerlaufkosten von 150 bis über 400 US-Dollar pro Monat. Auf der anderen Seite erzwingen kommerzielle Plattformen (wie Midjourney oder Leonardo) starre Monatsabonnements mit verfallenden Credits, die sich kaum für schwankende oder unregelmäßige Nutzerzugriffe eignen.

Dezgo schließt diese Lücke mit einer serverlosen REST-API auf echter Pay-as-you-go-Basis. Bei einer Mindestaufladung von lediglich 10 US-Dollar verfallen Guthaben nie. Standard-Renderings mit Stable Diffusion in 512x512 Pixeln kosten rund 0,0019 US-Dollar pro Bild und skalieren linear anhand von Pixelauflösung und Sampling-Schritten.

Dieser Leitfaden führt Full-Stack- und Backend-Entwickler durch die produktionsreife Integration der offiziellen Dezgo REST-API: Authentifizierung über X-Dezgo-Key, Anbindung der Endpunkte /text2image und /inpainting_sdxl, Guthabenüberwachung in Echtzeit über HTTP-Antwort-Header sowie die Entkopplung langlaufender Render-Vorgänge mittels asynchroner Worker-Warteschlangen.


Architektureller Vergleich: Eigene GPUs vs. SaaS-Abos vs. Dezgo

Vor der Implementierung empfiehlt sich ein strukturierter Vergleich der Ansätze:

KriteriumEigener GPU-Cluster (EC2 / RunPod)Kommerzielle SaaS (Midjourney etc.)Dezgo REST-API
Monatliche MindestkostenHoch ($150–$500+ Basispreis bei Leerlauf)Mittel bis Hoch ($10–$60+ pro Nutzer/Monat)Keine ($10 Einmal-Prepaid; Abrechnung pro Aufruf)
EinzelbildkostenStark schwankend; ineffizient bei wenig TrafficPauschalpakete; ungenutzte Punkte verfallen~$0,0019 pro 512px SD-Bild; transparente Cent-Bruchteile
WartungsaufwandSehr hoch (Treiber, Skalierung, Speicherlecks)Minimal (vollständig gemanagte Plattform)Minimal (reine HTTP-REST-Aufrufe; null GPU-Ops)
ModellflexibilitätMaximal (jedes HuggingFace-Modell und LoRA)Gering (nur proprietäre Modelle des Anbieters)Hoch (SD 1.5, SD 2.1, SDXL, SDXL Lightning, LoRAs)
Antwort-SchnittstelleEigenes API-Design und Streaming erforderlichOft Discord-Bots oder inoffizielle ScraperSynchroner binärer Bild-Stream (image/png) direkt

Dezgo liefert die fertige Bilddatei unmittelbar im Body der HTTP-Antwort zurück und übermittelt präzise Abrechnungs- und Saldo-Metadaten in den Headern.


Authentifizierung und Sicherheitsarchitektur

Alle Anfragen an die Dezgo-API müssen über den HTTP-Header X-Dezgo-Key authentifiziert werden. Der API-Schlüssel wird im Kontobereich unter dezgo.com/account erzeugt.

Die goldene Regel: Dezgo niemals direkt im Browser-Client aufrufen

Da Dezgo-Schlüssel direkt an das hinterlegte Echtgeld-Prepaid-Guthaben gebunden sind und keine Berechtigungs-Sandboxes für Endbenutzer existieren, birgt die Offenlegung von X-Dezgo-Key im Frontend-Code oder im Netzwerk-Tab ein massives Sicherheits- und Finanzrisiko. Dritte könnten den Schlüssel auslesen und das Guthaben in wenigen Minuten leeren.

Eine sichere Webarchitektur leitet alle Anfragen stets über ein vertrauenswürdiges Backend oder einen API-Proxy:

[Browser-Client]
       │
       │ 1. POST /api/generate (Benutzersitzung / Token-Abzug)
       ▼
[Eigenes Anwendungs-Backend]
       │
       │ 2. Eingaben validieren, Benutzerkontingente prüfen
       │ 3. Geheimen Header "X-Dezgo-Key" einfügen
       │ 4. POST https://api.dezgo.com/text2image
       ▼
[Dezgo REST-Cluster]
       │
       │ 5. Binärer PNG-Stream + Abrechnungs-Header
       ▼
[Eigenes Anwendungs-Backend]
       │
       │ 6. x-dezgo-job-amount-usd & x-dezgo-balance-total-usd auswerten
       │ 7. Bild in Objektspeicher (S3 / R2) sichern oder streamen
       ▼
[Browser-Client]

Schritt 1: Text-to-Image-Integration (/text2image)

Der Text-zu-Bild-Endpunkt akzeptiert Parameter wahlweise via multipart/form-data oder application/json (mit Base64-Kodierung) und gibt das gerenderte Bild als binären Datenstrom (image/png oder image/jpeg) zurück.

Wichtigste Anfrage-Parameter

Node.js / TypeScript Backend-Implementierung

// server/services/dezgoService.ts
import { Buffer } from "node:buffer";

interface TextToImageOptions {
  prompt: string;
  negativePrompt?: string;
  model?: string;
  guidance?: number;
  steps?: number;
  width?: number;
  height?: number;
}

interface GenerationResult {
  imageBuffer: Buffer;
  contentType: string;
  jobCostUsd: number;
  remainingBalanceUsd: number;
}

export async function generateTextToImage(
  options: TextToImageOptions
): Promise<GenerationResult> {
  const apiKey = process.env.DEZGO_API_KEY;
  if (!apiKey) {
    throw new Error("Umgebungsvariable DEZGO_API_KEY ist nicht definiert.");
  }

  const formData = new FormData();
  formData.append("prompt", options.prompt);
  if (options.negativePrompt) {
    formData.append("negative_prompt", options.negativePrompt);
  }
  if (options.model) {
    formData.append("model", options.model);
  }
  if (options.guidance) {
    formData.append("guidance", options.guidance.toString());
  }
  if (options.steps) {
    formData.append("steps", options.steps.toString());
  }
  if (options.width) {
    formData.append("width", options.width.toString());
  }
  if (options.height) {
    formData.append("height", options.height.toString());
  }

  const response = await fetch("https://api.dezgo.com/text2image", {
    method: "POST",
    headers: {
      "X-Dezgo-Key": apiKey,
    },
    body: formData,
  });

  if (!response.ok) {
    const errorText = await response.text();
    handleDezgoError(response.status, errorText);
  }

  // Auswertung der Abrechnungs- und Saldo-Header
  const jobCostUsd = parseFloat(
    response.headers.get("x-dezgo-job-amount-usd") || "0"
  );
  const remainingBalanceUsd = parseFloat(
    response.headers.get("x-dezgo-balance-total-usd") || "0"
  );

  const arrayBuffer = await response.arrayBuffer();
  const imageBuffer = Buffer.from(arrayBuffer);
  const contentType = response.headers.get("content-type") || "image/png";

  return {
    imageBuffer,
    contentType,
    jobCostUsd,
    remainingBalanceUsd,
  };
}

function handleDezgoError(status: number, message: string): never {
  switch (status) {
    case 400:
      throw new Error(`Dezgo Ungültige Anfrage (400): ${message}`);
    case 401:
      throw new Error("Dezgo Authentifizierungsfehler (401): X-Dezgo-Key prüfen.");
    case 402:
      throw new Error("Dezgo Guthaben erschöpft (402): Prepaid-Konto aufladen.");
    case 429:
      throw new Error("Dezgo Ratenlimit erreicht (429): Zu viele parallele Anfragen.");
    default:
      throw new Error(`Dezgo Serverfehler (${status}): ${message}`);
  }
}

Schritt 2: SDXL Inpainting-Integration (/inpainting_sdxl)

Inpainting ermöglicht die gezielte Überarbeitung markierter Bildbereiche bei voller Beibehaltung der restlichen Komposition. Dezgo stellt zwei Hauptendpunkte bereit: /inpainting (für reguläre Stable Diffusion Modelle) und /inpainting_sdxl (auf Basis von Stable Diffusion XL für hochauflösende Details).

Spezifikation der Eingabebilder

Für Inpainting werden zwei Dateien zwingend benötigt:

  1. init_image: Das originale Ausgangsbild (PNG oder JPEG).
  2. mask_image: Ein monochromes Maskenbild mit exakt denselben Pixelabmessungen wie init_image. Weiße Bereiche (#FFFFFF) markieren die Zone, die neu generiert werden soll; schwarze Pixel (#000000) bleiben unberührt.

Python Backend-Implementierung (FastAPI / Requests)

# app/services/dezgo_inpainting.py
import os
import requests
from typing import Dict, Any, Tuple

DEZGO_API_KEY = os.environ.get("DEZGO_API_KEY")
INPAINTING_SDXL_URL = "https://api.dezgo.com/inpainting_sdxl"

def execute_sdxl_inpainting(
    prompt: str,
    init_image_bytes: bytes,
    mask_image_bytes: bytes,
    negative_prompt: str = "",
    guidance: float = 7.5,
    steps: int = 30,
) -> Tuple[bytes, Dict[str, Any]]:
    """
    Sendet einen SDXL-Inpainting-Auftrag via multipart/form-data an Dezgo.
    """
    if not DEZGO_API_KEY:
        raise ValueError("DEZGO_API_KEY ist nicht in den Umgebungsvariablen gesetzt.")

    headers = {
        "X-Dezgo-Key": DEZGO_API_KEY
    }

    files = {
        "init_image": ("init.png", init_image_bytes, "image/png"),
        "mask_image": ("mask.png", mask_image_bytes, "image/png"),
    }

    data = {
        "prompt": prompt,
        "negative_prompt": negative_prompt,
        "guidance": str(guidance),
        "steps": str(steps),
    }

    response = requests.post(
        INPAINTING_SDXL_URL,
        headers=headers,
        files=files,
        data=data,
        timeout=60
    )

    if response.status_code == 402:
        raise RuntimeError("Dezgo-Prepaid-Guthaben aufgebraucht. Bitte nachladen.")
    elif response.status_code != 200:
        raise RuntimeError(f"Dezgo Inpainting fehlgeschlagen [{response.status_code}]: {response.text}")

    metadata = {
        "job_cost_usd": float(response.headers.get("x-dezgo-job-amount-usd", "0")),
        "remaining_balance_usd": float(response.headers.get("x-dezgo-balance-total-usd", "0")),
        "content_type": response.headers.get("Content-Type", "image/png"),
    }

    return response.content, metadata

Schritt 3: Asynchrone Abläufe und Timeout-Prävention

Die Dezgo-API arbeitet synchron: Der HTTP-Verbindungsaufbau bleibt bestehen, bis die Bildgenerierung abgeschlossen ist (typischerweise 2 bis 8 Sekunden). In Serverless-Umgebungen mit engen Ausführungsfristen (z. B. das 10-Sekunden-Limit bei kostenlosen Vercel-Deployments) führt dies leicht zu Gateway-Timeouts.

Empfohlenes Muster: Redis-Warteschlange mit Server-Sent Events (SSE)

In Produktionsumgebungen entkoppelt man die Client-Anfrage von der Bildberechnung mithilfe einer Redis-Warteschlange (z. B. BullMQ oder Celery):

[Web-Client] ── 1. POST /api/jobs (Prompt & Maske) ──► [Web-API-Server]
                                                            │
                                                            ▼
[Web-Client] ◄─ 3. 202 Accepted { jobId } ────── 2. Job in Redis-Queue
       │                                                    │
       │                                                    ▼
       │ 4. Warten via SSE / WebSocket oder Polling   [Redis / BullMQ]
       │                                                    │
       │                                                    ▼ 5. Task abholen
       │                                            [Hintergrund-Worker]
       │                                                    │
       │                                                    ├── 6. Dezgo aufrufen
       │                                                    ├── 7. Bild in S3/R2 sichern
       │                                                    └── 8. DB-Status aktualisieren
       ◄── 9. Event COMPLETED mit CDN-Bildlink melden ──────┘

BullMQ Worker-Beispiel

// workers/renderWorker.ts
import { Worker, Job } from "bullmq";
import { generateTextToImage } from "../services/dezgoService";
import { uploadToS3 } from "../services/storageService";
import { db } from "../services/db";

export const renderWorker = new Worker("image-generation-queue", async (job: Job) => {
  const { prompt, userId, jobId } = job.data;

  // 1. Dezgo aufrufen
  const { imageBuffer, contentType, jobCostUsd, remainingBalanceUsd } =
    await generateTextToImage({ prompt, steps: 30 });

  // 2. Im Cloudflare R2 / S3 Objektspeicher ablegen
  const cdnUrl = await uploadToS3({
    key: `renders/${userId}/${jobId}.png`,
    body: imageBuffer,
    contentType,
  });

  // 3. Datenbankeintrag und Kostenabrechnung aktualisieren
  await db.jobs.update({
    where: { id: jobId },
    data: {
      status: "COMPLETED",
      outputUrl: cdnUrl,
      costUsd: jobCostUsd,
    },
  });

  // 4. Saldo-Warnung bei weniger als 5 US-Dollar
  if (remainingBalanceUsd < 5.0) {
    console.warn(`[Guthaben-Warnung] Dezgo API Saldo gering: Noch $${remainingBalanceUsd.toFixed(2)}.`);
  }

  return { cdnUrl, jobCostUsd };
});

Kontoverwaltung und Absicherung im Produktivbetrieb

Dezgo unterstützt keine automatische Kreditkarten-Nachladung; Beträge müssen manuell vor dem Erreichen des Null-Saldos aufgeladen werden. Die Überwachung der Header-Werte ist daher unabdingbar.

Metadaten in HTTP-Antwort-Headern

Saldoabfrage ohne Bildgenerierung

Um den Kontostand ohne Bildberechnungskosten abzufragen, existiert der Transaktionsendpunkt:

curl -s -H "X-Dezgo-Key: YOUR_API_KEY" https://api.dezgo.com/account/tx/last

Die Antwort liefert ein JSON-Objekt mit der letzten Transaktion und dem aktuellen balance-Feld.

Fehlerbehandlung im Überblick

  1. HTTP 402 (Payment Required): Prepaid-Guthaben ist erschöpft. Fangen Sie diesen Status im Backend ab, um das Team sofort via PagerDuty/Slack zu alarmieren und dem Anwender eine saubere Hinweismeldung („Wartung in Bearbeitung“) anstelle eines 500er-Fehlers anzuzeigen.
  2. HTTP 429 (Too Many Requests): Ratenlimit erreicht. Nutzen Sie exponentielles Backoff mit Jitter im Worker.
  3. HTTP 400 (Bad Request): Tritt meist bei abweichenden Auflösungen zwischen Maske und Originalbild auf. Validieren Sie Bilddimensionen immer client- oder serverseitig vor dem Absenden.

Fazit

Für Solo-Entwickler und agile Start-ups bietet Dezgo eine kosteneffiziente Alternative zum wartungsintensiven GPU-Hosting und teuren Monatsabos. Mit einem geschützten Backend-Proxy, einer Redis-Warteschlange für langlaufende Anfragen und kontinuierlicher Saldoüberwachung lässt sich eine skalierbare Bildgenerierung mit Stückkosten im Bruchteil-Cent-Bereich zuverlässig betreiben.

Referenzen