Skip to content
Alle Beiträge
Blog·5. März 2026

Wie die Screenshots Live Render API funktioniert — Ein praktischer Guide für Store-Listing-Automatisierung

Ein technischer Walkthrough, wie die Screenshots Live Render API Templates verarbeitet, YAML-Overrides anwendet und store-fertige Screenshots erstellt — mit echten Code-Beispielen und CI/CD-Patterns für Whitelabel-Setups.

Was dieser Post abdeckt

Wer Whitelabel-Apps ausliefert — oder auch nur eine einzige App mit mehreren Store-Listings pflegt — kennt das Screenshot-Problem. Apple will Screenshots für jede Gerätegröße. Google Play will seinen eigenen Satz. Drei Sprachen unterstützen bedeutet dreifache Arbeit. Jetzt multiplizier das mit der Anzahl deiner Marken-Varianten.

Der vorherige Post hat erklärt, warum Screenshots Live existiert. Dieser hier ist die praktische Fortsetzung: wie die Render API aufgebaut ist, was sie erwartet und wie du sie in deine Build-Pipeline einbaust, damit Screenshots nicht mehr Handarbeit sind.

Wie die Render Pipeline aufgebaut ist

Das Render-System ist kein synchroner "Request rein, Bild raus"-Endpoint. Es ist eine Job-basierte Pipeline — das wird wichtig, sobald du dutzende oder hunderte Screenshots im Batch renderst.

Der Ablauf:

  1. Du schickst einen Render-Request mit einer Template-ID und optionalen YAML-Overrides (Text, Screenshots, Device Frames — alles, was als austauschbar markiert ist).
  2. Validierung — das System prüft, ob dein Template existiert, ob es dir gehört und ob jedes Feld, das du überschreiben willst, tatsächlich erlaubt ist. URLs werden gegen private IP-Bereiche und eingeschränkte Protokolle validiert.
  3. Warteschlange — der Job landet in einer Redis-basierten BullMQ Queue. Dein API-Call kehrt sofort mit einer jobId und Status Pending zurück. Das ist der Punkt: du wartest nicht auf das Rendering.
  4. Rendering — ein Rust-basierter Worker holt den Job ab, lädt Template und Bilder (mit LRU-Caching für wiederholte Renders), lädt Schriften, rendert den Canvas mit Skia und erzeugt die Ausgabe.
  5. Verpackung — die gerenderten Bilder werden gezippt und in den Object Storage hochgeladen.
  6. Download — du pollst den Status-Endpoint. Bei Completed holst du dir über den Download-Endpoint eine vorsignierte URL (1 Stunde gültig).

Das asynchrone Design ist Absicht. Wenn du 50 Templates für einen Release rendern musst, feuerst du alle ab und sammelst die Ergebnisse ein. Kein Blocking, keine Timeouts.

Authentifizierung

Du brauchst einen Pro-Tier-Account für die Render API. Erstell einen API-Key in deinem Dashboard — er sieht aus wie sa_live_.... Jeder Request nutzt ihn als Bearer Token:

Authorization: Bearer sa_live_your_key_here

Templates: Wie sie aufgebaut sind

Alles dreht sich um Templates. Ein Template ist ein Canvas, den du im visuellen Editor baust — du platzierst Textblöcke, Device Frames, Bilder und Hintergründe. Jedes Element auf dem Canvas ist ein Item mit einer eigenen UUID.

Für die Automatisierung ist das zentrale Konzept: Austauschbare Felder (Swappable Fields). Nicht jede Eigenschaft jedes Items kann über die API überschrieben werden. Ein Admin konfiguriert, welche Felder austauschbar sind — Textinhalt, Schriftfamilie, Schriftgröße, Farben, Screenshot-URLs, Device-Frame-IDs usw. Das ist eine bewusste Einschränkung: sie verhindert, dass API-Nutzer versehentlich das Layout kaputt machen, indem sie Positionen oder Größen ändern, die der Designer festgelegt hat.

Stell es dir als Vertrag zwischen Designer und Pipeline vor: der Designer bestimmt das Layout, die Pipeline bestimmt den Inhalt.

Das YAML Override System

Hier wird es spannend für die Automatisierung. Anstatt ein Template genau so zu rendern wie gespeichert, schickst du YAML, das bestimmte Felder bestimmter Items überschreibt.

Schritt 1: YAML-Gerüst holen

Jedes Template hat einen Scaffold-Endpoint, der alle austauschbaren Felder als kommentiertes YAML liefert:

curl -H "Authorization: Bearer sa_live_your_key_here" \
  https://api.screenshots.live/templates/DEINE_TEMPLATE_ID/yaml

Du bekommst sowas:

templateId: "550e8400-e29b-41d4-a716-446655440000"
items:
  - itemId: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
    type: Text
    # text: "Deine Überschrift"
    # fontFamily: "Inter"
    # fontSize: 48
    # color: "#FFFFFF"
  - itemId: "a1b2c3d4-5678-90ab-cdef-1234567890ab"
    type: DeviceFrame
    # screenshotUrl: "https://..."
    # frameId: "..."

Kommentiere aus, was du überschreiben willst. Lass den Rest — diese Felder behalten ihre Template-Standardwerte.

Schritt 2: Render absenden

curl -X POST https://api.screenshots.live/render/api \
  -H "Authorization: Bearer sa_live_your_key_here" \
  -H "Content-Type: text/yaml" \
  -d '
templateId: "550e8400-e29b-41d4-a716-446655440000"
items:
  - itemId: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
    type: Text
    text: "Verfolge deine Lieferungen"
    color: "#1A73E8"
  - itemId: "a1b2c3d4-5678-90ab-cdef-1234567890ab"
    type: DeviceFrame
    screenshotUrl: "https://your-cdn.com/screenshots/home-screen.png"
'

Antwort:

{
  "data": {
    "jobId": "d4e5f6a7-8901-2345-6789-0abcdef12345",
    "templateId": "550e8400-e29b-41d4-a716-446655440000",
    "status": "Pending",
    "createdAt": "2026-03-05T10:30:00.000Z"
  }
}

Schritt 3: Status abfragen

curl -H "Authorization: Bearer sa_live_your_key_here" \
  https://api.screenshots.live/render/api/JOB_ID

Der Status durchläuft PendingActiveCompleted (oder Failed). Die meisten Templates werden in wenigen Sekunden gerendert.

Schritt 4: Download

curl -H "Authorization: Bearer sa_live_your_key_here" \
  https://api.screenshots.live/render/JOB_ID/download

Liefert eine vorsignierte URL. Der Download ist ein ZIP mit den gerenderten Bildern.

Screenshots direkt hochladen

Du musst deine Screenshots nicht irgendwo hosten, nur um eine URL zu übergeben. Der /render/api/with-pictures Endpoint akzeptiert Multipart-Uploads:

curl -X POST https://api.screenshots.live/render/api/with-pictures \
  -H "Authorization: Bearer sa_live_your_key_here" \
  -F 'yaml=templateId: "DEINE_TEMPLATE_ID"
items:
  - itemId: "DEVICE_FRAME_ITEM_ID"
    type: DeviceFrame
    screenshotUrl: "picture://home-screen.png"' \
  -F 'pictures=@./screenshots/home-screen.png'

Das picture://-Protokoll referenziert hochgeladene Dateien über den Dateinamen. Bis zu 200 Dateien, je max 10MB. Das macht die API praktisch für CI/CD — deine Pipeline macht Screenshots, und du schickst sie direkt ans Rendering, ohne Zwischenspeicher.

Praxis-Beispiel: Whitelabel Pipeline

Ein konkretes Szenario: du betreust 5 Whitelabel-Marken, jede braucht App Store Screenshots in 3 Sprachen über 5 Bildschirme. Das sind 75 gerenderte Bilder pro Release.

Dein Designer hat pro Screen ein Template im Editor erstellt, mit Headline-Text und Device Frame als austauschbare Items. Deine CI-Pipeline (GitLab, GitHub Actions, egal) erstellt mit Fastlanes snapshot/screengrab die Roh-Screenshots pro Marke und Sprache.

Hier das Script, das alles zusammenbringt:

#!/bin/bash

API_KEY="sa_live_your_key_here"
API_BASE="https://api.screenshots.live"

BRANDS=("acme" "globex" "initech" "umbrella" "stark")
LOCALES=("en" "de" "es")
SCREENS=("home" "profile" "search" "settings" "checkout")

declare -A TEMPLATES
TEMPLATES[home]="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
TEMPLATES[profile]="aaaaaaaa-bbbb-cccc-dddd-ffffffffffff"

declare -A HEADLINES
HEADLINES[home:en]="Track your deliveries"
HEADLINES[home:de]="Verfolge deine Lieferungen"
HEADLINES[home:es]="Rastrea tus entregas"

JOB_IDS=()

for brand in "${BRANDS[@]}"; do
  for locale in "${LOCALES[@]}"; do
    for screen in "${SCREENS[@]}"; do
      HEADLINE="${HEADLINES[$screen:$locale]}"
      BRAND_COLOR=$(cat "brands/$brand/primary-color.txt")

      RESPONSE=$(curl -s -X POST "$API_BASE/render/api/with-pictures" \
        -H "Authorization: Bearer $API_KEY" \
        -F "yaml=templateId: \"${TEMPLATES[$screen]}\"
items:
  - itemId: \"TEXT_ITEM_UUID\"
    type: Text
    text: \"$HEADLINE\"
    color: \"$BRAND_COLOR\"
  - itemId: \"FRAME_ITEM_UUID\"
    type: DeviceFrame
    screenshotUrl: \"picture://${screen}.png\"" \
        -F "pictures=@./artifacts/$brand/$locale/${screen}.png")

      JOB_ID=$(echo "$RESPONSE" | jq -r '.data.jobId')
      JOB_IDS+=("$JOB_ID|$brand|$locale|$screen")
    done
  done
done

echo "${#JOB_IDS[@]} Jobs abgeschickt. Warte auf Ergebnisse..."

for entry in "${JOB_IDS[@]}"; do
  IFS='|' read -r job_id brand locale screen <<< "$entry"
  while true; do
    STATUS=$(curl -s -H "Authorization: Bearer $API_KEY" \
      "$API_BASE/render/api/$job_id" | jq -r '.status')
    if [ "$STATUS" = "Completed" ]; then
      URL=$(curl -s -H "Authorization: Bearer $API_KEY" \
        "$API_BASE/render/$job_id/download" | jq -r '.downloadUrl')
      mkdir -p "./output/$brand/$locale"
      curl -s -o "./output/$brand/$locale/${screen}.zip" "$URL"
      echo "Fertig: $brand/$locale/$screen"
      break
    elif [ "$STATUS" = "Failed" ]; then
      echo "FEHLER: $brand/$locale/$screen"
      break
    fi
    sleep 2
  done
done

75 Render-Jobs, alle parallel abgefeuert, dann gepollt und heruntergeladen. In einer echten Pipeline würdest du Retry-Logik und paralleles Polling einbauen, aber das Muster ist klar. Bau das in deine .gitlab-ci.yml oder GitHub Actions ein und der ganze Ablauf — vom Code-Push bis zu store-fertigen Screenshots — läuft ohne menschliches Zutun.

Device Frames wechseln

Device Frames sind die Mockup-Overlays — iPhone 16 Pro, Pixel 9, iPad Air, Galaxy S24. Sie sind in deinem Account vorgeladen und werden per UUID referenziert. Dasselbe Template kann mit verschiedenen Device Frames gerendert werden:

items:
  - itemId: "FRAME_ITEM_UUID"
    type: DeviceFrame
    screenshotUrl: "picture://home.png"
    frameId: "IPHONE_16_PRO_FRAME_UUID"

So löst du die App Store vs Google Play Aufteilung: gleiches Template-Layout, gleicher Screenshot, anderer Frame. Zwei Render-Jobs — einer mit dem iPhone-Frame, einer mit dem Pixel-Frame — und du hast beide Stores mit einem Template abgedeckt.

Rate Limits und Kontingente

Zahlen zur Planung:

  • Render API: 5 Requests pro 60 Sekunden
  • Status-Polling: 60 Requests pro 60 Sekunden
  • Tägliche Renders: 100 pro Tag im Pro-Tier
  • Bild-Uploads: max 200 Dateien pro Request, je 10MB

Bei großen Whitelabel-Setups ist das Rate Limit bei den Render-Submissions der Flaschenhals. Bau kleine Pausen zwischen den Batches ein. Das async Design hilft — Submissions sind schnell, das eigentliche Rendering passiert im Hintergrund.

YAML Validierung

Der YAML Parser ist bewusst strikt: keine Anker, keine Aliase, keine Custom Tags, max 1MB. Wenn was nicht stimmt, sagt die Fehlermeldung genau was — falscher Feldname, nicht-austauschbares Feld, ungültiges UUID-Format, URL auf einen privaten IP-Bereich. Designed um schnell und klar zu scheitern — das zählt, wenn du um 23 Uhr eine CI-Pipeline debuggst.

Was ist mit dem OpenAPI Spec?

Wenn du lieber einen typisierten Client generierst statt curl-Kommandos zu schreiben, der vollständige OpenAPI Spec ist verfügbar unter:

https://api.screenshots.live/render/openapi.json

Und es gibt eine interaktive Swagger UI unter:

https://api.screenshots.live/render/docs

Beides braucht Pro-Tier-Authentifizierung. Der Spec deckt alle Render-Endpoints, DTOs und Fehlerantworten ab — füttere ihn in openapi-generator oder orval und du hast einen typisierten Client in TypeScript, Python, Go oder was auch immer.

Fazit

Die Render API ist für einen bestimmten Workflow gebaut: dein Designer erstellt Templates im visuellen Editor, und dein Code füllt sie zur Build-Zeit mit dem richtigen Inhalt. Für Whitelabel-Setups, bei denen dasselbe Template für dutzende Marken und Sprachen funktionieren muss, bedeutet das YAML-Override-System: du pflegst ein Template pro Screen-Layout, statt eins pro Marke-Sprache-Geräte-Kombination.

Wenn du die Roh-Screenshots im Griff hast (Fastlane, Maestro, manuelle Captures — egal) und den Verarbeitungsschritt automatisieren willst, dafür ist Screenshots Live da. Die Pipeline macht Screenshots, die API rendert sie zu store-fertigen Bildern und Fastlane lädt sie hoch. Kein Designer im Loop für Routine-Releases.