Come funziona la Render API di Screenshots Live — Guida pratica per automatizzare i listing degli store
Un walkthrough tecnico su come la Render API di Screenshots Live elabora i template, applica gli override YAML e genera screenshot pronti per lo store — con esempi di codice reali e pattern CI/CD per setup whitelabel.
Cosa copre questo post
Se distribuisci app whitelabel — o anche solo un'app con più listing negli store — probabilmente ti sei già scontrato con il problema degli screenshot. Apple vuole screenshot per ogni dimensione di dispositivo. Google Play vuole il suo set. Supporta tre lingue e hai triplicato il lavoro. Adesso moltiplica tutto per il numero di varianti di brand che mantieni.
Il post precedente ha spiegato perché esiste Screenshots Live. Questo è il seguito pratico: come è progettata la render API, cosa si aspetta e come integrarla nella tua build pipeline perché gli screenshot smettano di essere un lavoro manuale.
Come è progettata la pipeline di rendering
Il sistema di rendering non è un endpoint sincrono "mandi la request, ricevi l'immagine". È una pipeline basata su job, il che conta quando fai rendering batch di decine o centinaia di screenshot.
Il flusso:
- Invii una richiesta di rendering con un ID template e override YAML opzionali (testo, screenshot, device frame — qualsiasi cosa marcata come intercambiabile).
- Validazione — il sistema verifica che il tuo template esista, che sia tuo e che ogni campo che vuoi sovrascrivere sia effettivamente permesso. Gli URL vengono validati contro range IP privati e protocolli ristretti.
- Coda — il job entra in una coda BullMQ basata su Redis. La tua chiamata API ritorna immediatamente con un
jobIde statoPending. Questo è il punto chiave: non aspetti che il rendering finisca. - Rendering — un worker basato su Rust prende il job, carica template e immagini (con cache LRU per render ripetuti), carica i font, renderizza il canvas usando Skia e genera l'output.
- Pacchettizzazione — le immagini renderizzate vengono zippate e caricate nell'object storage.
- Download — fai polling sull'endpoint di stato. Quando è
Completed, chiami l'endpoint di download per un URL prefirmato (valido per 1 ora).
Il design asincrono è intenzionale. Quando devi renderizzare 50 template per un release, li spari tutti e raccogli i risultati. Nessun blocco, nessun timeout.
Autenticazione
Serve un account Pro tier per accedere alla render API. Crea un API key dalla tua dashboard — apparirà come sa_live_.... Ogni richiesta lo usa come Bearer token:
Authorization: Bearer sa_live_your_key_here
Template: Come sono strutturati
Tutto ruota attorno ai template. Un template è un canvas che costruisci nell'editor visuale — piazzi blocchi di testo, device frame, immagini e sfondi. Ogni elemento sul canvas è un item con un UUID unico.
Per l'automazione, il concetto critico sono i campi intercambiabili (swappable field). Non ogni proprietà di ogni item è sovrascrivibile via API. Un admin configura quali campi sono intercambiabili — contenuto testuale, famiglia di font, dimensione font, colori, URL screenshot, ID device frame, ecc. È una restrizione deliberata: impedisce ai consumatori dell'API di rompere accidentalmente il layout cambiando posizioni o dimensioni che il designer ha fissato.
Pensalo come un contratto tra il tuo designer e la tua pipeline: il designer è proprietario del layout, la pipeline è proprietaria del contenuto.
Il sistema di override YAML
Qui diventa interessante per l'automazione. Invece di renderizzare un template esattamente come è stato salvato, invii YAML che sovrascrive campi specifici di item specifici.
Step 1: Ottenere lo scaffold YAML
Ogni template ha un endpoint scaffold che restituisce tutti i campi intercambiabili come YAML commentato:
curl -H "Authorization: Bearer sa_live_your_key_here" \
https://api.screenshots.live/templates/IL_TUO_TEMPLATE_ID/yaml
Riceverai qualcosa tipo:
templateId: "550e8400-e29b-41d4-a716-446655440000"
items:
- itemId: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
type: Text
# text: "Il tuo titolo qui"
# fontFamily: "Inter"
# fontSize: 48
# color: "#FFFFFF"
- itemId: "a1b2c3d4-5678-90ab-cdef-1234567890ab"
type: DeviceFrame
# screenshotUrl: "https://..."
# frameId: "..."
Decommenta quello che vuoi sovrascrivere. Lascia il resto — quei campi mantengono i valori predefiniti del template.
Step 2: Inviare il render
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: "Traccia le tue consegne"
color: "#1A73E8"
- itemId: "a1b2c3d4-5678-90ab-cdef-1234567890ab"
type: DeviceFrame
screenshotUrl: "https://your-cdn.com/screenshots/home-screen.png"
'
Step 3: Controllare lo stato
curl -H "Authorization: Bearer sa_live_your_key_here" \
https://api.screenshots.live/render/api/JOB_ID
Lo stato progredisce: Pending → Active → Completed (o Failed). La maggior parte dei template viene renderizzata in pochi secondi.
Step 4: Scaricare
curl -H "Authorization: Bearer sa_live_your_key_here" \
https://api.screenshots.live/render/JOB_ID/download
Restituisce un URL prefirmato. Il download è un ZIP con le immagini renderizzate.
Caricare screenshot direttamente
Non serve hostare gli screenshot da qualche parte solo per passare un URL. L'endpoint /render/api/with-pictures accetta upload multipart:
curl -X POST https://api.screenshots.live/render/api/with-pictures \
-H "Authorization: Bearer sa_live_your_key_here" \
-F 'yaml=templateId: "IL_TUO_TEMPLATE_ID"
items:
- itemId: "DEVICE_FRAME_ITEM_ID"
type: DeviceFrame
screenshotUrl: "picture://home-screen.png"' \
-F 'pictures=@./screenshots/home-screen.png'
Il protocollo picture:// referenzia i file caricati per nome. Puoi allegare fino a 200 file da 10MB ciascuno. Questo è ciò che rende l'API pratica per CI/CD — la tua pipeline cattura screenshot e li mandi direttamente al rendering senza storage intermedio.
Esempio reale: Pipeline whitelabel
Uno scenario concreto: gestisci 5 brand whitelabel, ognuno necessita di screenshot App Store in 3 lingue per 5 schermate chiave. Sono 75 immagini renderizzate per release.
Il tuo designer ha creato un template per schermata nell'editor, con testo headline e device frame marcati come intercambiabili. La tua pipeline CI (GitLab, GitHub Actions, qualsiasi cosa) cattura screenshot raw per brand e lingua con snapshot/screengrab di Fastlane.
Lo script che unisce tutto:
#!/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[@]} job inviati. In attesa dei risultati..."
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 "Fatto: $brand/$locale/$screen"
break
elif [ "$STATUS" = "Failed" ]; then
echo "ERRORE: $brand/$locale/$screen"
break
fi
sleep 2
done
done
75 render job, tutti sparati in parallelo, poi polled e scaricati. In una pipeline reale aggiungeresti retry logic e polling parallelo, ma il pattern è chiaro. Inseriscilo nel tuo .gitlab-ci.yml o GitHub Actions e l'intero flusso — dal push del codice agli screenshot pronti per lo store — gira senza intervento umano.
Scambiare device frame
I device frame sono gli overlay mockup — iPhone 16 Pro, Pixel 9, iPad Air, Galaxy S24. Sono precaricati nel tuo account e referenziati per UUID. Lo stesso template può essere renderizzato con frame diversi:
items:
- itemId: "FRAME_ITEM_UUID"
type: DeviceFrame
screenshotUrl: "picture://home.png"
frameId: "IPHONE_16_PRO_FRAME_UUID"
Così risolvi la divisione App Store vs Google Play: stesso layout template, stesso screenshot, frame diverso. Due render job — uno con il frame iPhone, uno con il Pixel — e hai coperto entrambi gli store con un solo template.
Rate limit e quote
Numeri per pianificare:
- Render API: 5 richieste ogni 60 secondi
- Polling stato: 60 richieste ogni 60 secondi
- Render giornalieri: 100 al giorno su Pro tier
- Upload immagini: max 200 file per richiesta, 10MB ciascuno
Per setup whitelabel grandi, il rate limit sulle submission di render è il collo di bottiglia. Aggiungi piccole pause tra i batch. Il design async aiuta — le submission sono veloci, il rendering effettivo avviene in background.
Validazione YAML
Il parser YAML è deliberatamente rigoroso: niente ancore, niente alias, niente tag custom, max 1MB. Se qualcosa non va, il messaggio di errore ti dice esattamente cosa — nome campo sbagliato, campo non intercambiabile, formato UUID non valido, URL che punta a un range IP privato. Progettato per fallire velocemente e chiaramente — conta quando stai debuggando una pipeline CI alle 23.
E lo spec OpenAPI?
Se preferisci generare un client tipizzato invece di scrivere comandi curl, lo spec OpenAPI completo è disponibile su:
https://api.screenshots.live/render/openapi.json
E c'è una Swagger UI interattiva su:
https://api.screenshots.live/render/docs
Entrambi richiedono autenticazione Pro tier. Lo spec copre tutti gli endpoint render, i DTO e le risposte di errore — passalo a openapi-generator o orval e avrai un client tipizzato in TypeScript, Python, Go o quello che usi.
Conclusione
La render API è costruita per un workflow specifico: il tuo designer crea template nell'editor visuale, e il tuo codice li riempie con il contenuto giusto al momento del build. Per setup whitelabel dove lo stesso template deve funzionare per decine di brand e lingue, il sistema di override YAML significa che mantieni un template per layout di schermata invece di uno per combinazione brand-lingua-dispositivo.
Se hai gli screenshot raw coperti (Fastlane, Maestro, catture manuali — non importa) e devi automatizzare lo step di elaborazione, a questo serve Screenshots Live. La pipeline cattura screenshot, l'API li renderizza in immagini pronte per lo store, e Fastlane li carica. Nessun designer nel loop per release di routine.