Große E-Commerce-Plattformen, Marktplatz-Händler und Multichannel-Betreiber stehen bei der Katalogaufnahme vor einer wiederkehrenden technischen Herausforderung: Produktfotos von Herstellern und Lieferanten weisen uneinheitliche Seitenverhältnisse, störende Kulissen und schwankende Belichtungen auf. Desktop-Programme zur Stapelverarbeitung erfordern manuelle Bedienung und lassen sich nicht direkt in automatisierte ERP-, PIM- (Product Information Management) oder CMS-Architekturen einbinden. Die manuelle Bearbeitung durch Grafiker verzögert die Veröffentlichung um 24 bis 72 Stunden pro Artikel und verursacht erhebliche Personalkosten pro SKU.
Cutout.pro bietet eine Entwickler-REST-API für Computer Vision, die das automatische Freistellen von Objekten, das Beschneiden von Bildrändern und das Ersetzen von Hintergründen durch Volltonfarben ermöglicht. Durch die Einbindung dieser API in eine asynchrone Backend-Pipeline können technische Teams Tausende von Rohbildern innerhalb von Sekunden in marktplatzkonforme Katalogbilder transformieren: mit reinweißem Hintergrund (#FFFFFF), standardisierten Proportionen und realistischen Kontaktschatten für Plattformen wie Amazon, eBay und Shopify.
1. API-Spezifikation und Authentifizierungsablauf
Cutout.pro stellt seine Dienste über standardisierte HTTPS-Endpunkte bereit. Die Authentifizierung erfolgt für alle Anfragen über einen benutzerdefinierten HTTP-Header:
APIKEY: ihr_cutout_pro_api_schluessel
Vorabprüfung des Guthabens in Produktionsumgebungen
Große Importläufe umfassen oft Zehntausende von Produktbildern. Wenn das Guthaben während eines laufenden Batches erschöpft ist, scheitern Anfragen massenhaft mit dem Fehlercode 4001 (Guthaben nicht ausreichend). Daher sollte jede Pipeline das verfügbare Guthaben vor dem Start großer Jobs abfragen.
Cutout.pro bietet hierfür einen dedizierten Endpunkt:
- Endpunkt:
GET https://www.cutout.pro/api/v1/mySubscription - Header:
APIKEY: <IHR_API_KEY>,Accept: application/json
Beispiel für eine erfolgreiche JSON-Antwort:
{
"code": 0,
"data": {
"monthBalance": 1250,
"imageBalance": 5000,
"videoBalance": 0,
"monthStartDate": "2026-10-01 00:00:00",
"monthExpireDate": "2026-11-01 00:00:00"
},
"msg": null,
"time": 1728729600000
}
Durch die Einbindung dieser Abfrage in den Pipeline-Orchestrator können Batches rechtzeitig pausiert und Warnungen an das Betriebsteam gesendet werden, bevor fehlerhafte API-Aufrufe entstehen.
2. Endpunkt-Modi und Konfigurationsparameter
Für das Freistellen von Handelswaren und E-Commerce-Artikeln empfiehlt Cutout.pro mattingType=6 (universelles Freistellen für Produkte, Kleidung und Gegenstände) oder mattingType=1. Die API unterstützt drei Übertragungsmodi:
| Modus | Endpunkt | Methode & Content-Type | Rückgabeformat | Empfohlener Einsatzzweck |
|---|---|---|---|---|
| Modus 1: Binärdatenstrom | https://www.cutout.pro/api/v1/matting | POST / multipart/form-data | Rohes Bildformat (image/png) | Direkte Speicherung auf Datenträgern oder in Speicherpuffern |
| Modus 2: Base64 in JSON | https://www.cutout.pro/api/v1/matting2 | POST / multipart/form-data | JSON mit data.imageBase64 | Microservices mit JSON-RPC-Kommunikation |
| Modus 3: Bild-URL | https://www.cutout.pro/api/v1/mattingByUrl | GET / Query-Parameter | JSON mit data.imageBase64 | Rohdaten liegen bereits auf AWS S3, Cloudflare R2 oder CDNs |
Wichtige Parameter für die E-Commerce-Standardisierung
mattingType(Integer, erforderlich): Für E-Commerce-Produkte auf6setzen.crop(Boolean, optional): Beitruewerden leere transparente Ränder automatisch entfernt und das Bild eng am Objekt beschnitten.cropMargin(String, optional): Definiert zusätzliche Ränder um das freigestellte Objekt beicrop=true. Unterstützt Pixelwerte (z. B."30px") oder Prozentangaben (z. B."10%").bgcolor(Hex-String, optional): Füllt den transparenten Bereich mit einer Volltonfarbe ohne#(z. B.FFFFFFfür Reinweiß). Der Spezialwert'blur'erzeugt einen weichgezeichneten Hintergrund.outputFormat(String, optional): Ausgabeformat (png,webpoderjpg_<Qualität>, z. B.jpg_85).preview(Boolean, optional): Beitruewird die Auflösung auf maximal 500x500 Pixel begrenzt und pro erfolgreichem Aufruf nur 0,25 Credit berechnet (im Vergleich zu 1 Credit für Vollauflösungen bis 4096x4096px und <15MB). Ideal für Entwurfsvorschauen im Händlerportal.
3. Asynchrone Warteschlangenarchitektur und Ratenbegrenzung
Die REST-API von Cutout.pro arbeitet synchron: Jede HTTP-Verbindung wartet, bis die Berechnung auf dem Server abgeschlossen ist. Allerdings gilt eine strikte Ratenbegrenzung von maximal 5 gleichzeitigen Anfragen pro Sekunde (5 QPS).
Wird diese Grenze durch unkontrollierte parallele Threads überschritten, antwortet die API mit dem Fehlercode 5005 (Too many requests in the queue, please wait). Für Kataloge mit Zehntausenden von Artikeln ist daher eine asynchrone Warteschlange mit Ratenbegrenzung erforderlich.
Architekturübersicht
[ERP / PIM Stapelimport]
│ (SKU-Batch übergeben)
▼
[Message Broker: Redis / RabbitMQ]
│
▼
[Worker-Cluster (Celery / BullMQ)]
├── Token-Bucket Rate Limiter (Gedrosselt auf <= 4.5 QPS)
├── Cutout.pro API-Aufruf (POST /api/v1/matting?mattingType=6)
│ └── Exponentielles Backoff bei Fehler 5005
├── Lokale Bildstandardisierung (Pillow / Sharp)
│ ├── Zentrierung auf quadratischer Leinwand (2000x2000px)
│ ├── 85% Produktflächenabdeckung
│ └── Erzeugung eines weichen Kontaktschattens (Contact Shadow)
├── Cloud-Upload (AWS S3 / Cloudflare R2)
└── Webhook-Callback an ERP (Produktstatus und Bild-URLs aktualisieren)
Fehlerbehandlung und Resilienz
- Zentrales Token-Bucket-Verfahren: Begrenzen Sie die ausgehenden Anfragen des gesamten Worker-Clusters über Redis auf maximal 4,5 QPS, um den Schwellenwert von 5 QPS sicher einzuhalten.
- Klassifizierung von Fehlern:
5005(Warteschlange voll): Exponentielles Backoff mit Jitter anwenden (Wartezeit: 1,5s, 3s, 6s).1002(Datei > 15MB) oder5008(Unbekanntes Format): Artikel in eine Dead-Letter-Queue (DLQ) verschieben und zur manuellen Prüfung im ERP markieren.4001(Guthaben aufgebraucht): Warteschlangenverarbeitung sofort stoppen und Alarm an das Betriebsteam auslösen.
4. Pipeline zur Bildstandardisierung: Maße, Rahmen und Schatten
Zwar kann Cutout.pro über bgcolor=FFFFFF direkt weiße Hintergründe liefern, Marktplatzrichtlinien von Amazon, Google Shopping und Shopify verlangen jedoch strengere geometrische Vorgaben:
- Das Bild muss exakt quadratisch sein (Seitenverhältnis 1:1, z. B. 2000x2000 Pixel).
- Das Produkt sollte 80% bis 85% der Leinwandfläche einnehmen, um eine einheitliche Galerieansicht zu gewährleisten.
- Ein freigestelltes Bild ohne Schatten wirkt auf reinweißem Grund künstlich wie ein Aufkleber. Ein dezenter, weicher Kontaktschatten an der Standfläche verleiht dem Artikel Tiefe und Wertigkeit.
Das bewährte Vorgehen besteht darin, von Cutout.pro ein transparentes PNG anzufordern (crop=true, ohne bgcolor) und die Einpassung in die weiße Leinwand sowie die Schattengenerierung lokal im Worker mit schnellen Bibliotheken wie Python Pillow oder Node.js Sharp durchzuführen.
Produktionsbeispiel in Python mit Pillow
import io
import time
import requests
from PIL import Image, ImageFilter
CUTOUT_API_KEY = "IHR_API_SCHLUESSEL"
API_URL = "https://www.cutout.pro/api/v1/matting?mattingType=6&crop=true"
def remove_background(image_bytes: bytes, max_retries: int = 3) -> bytes:
"""Ruft die Cutout.pro API mit exponentiellem Backoff bei Ratenbegrenzungen auf."""
headers = {"APIKEY": CUTOUT_API_KEY}
files = {"file": ("product.jpg", image_bytes, "image/jpeg")}
for attempt in range(max_retries):
response = requests.post(API_URL, headers=headers, files=files, timeout=30)
if response.status_code == 200 and response.headers.get("Content-Type", "").startswith("image/"):
return response.content
try:
err = response.json()
code = err.get("code")
msg = err.get("msg")
if code == 5005: # Rate Limit erreicht
time.sleep((2 ** attempt) + 0.5)
continue
elif code == 4001:
raise RuntimeError("Cutout.pro Guthaben ist aufgebraucht.")
else:
raise ValueError(f"Cutout.pro Fehler: {code} - {msg}")
except requests.exceptions.JSONDecodeError:
response.raise_for_status()
raise TimeoutError("Maximale Anzahl an Wiederholungsversuchen überschritten.")
def standardize_product_image(
transparent_png_bytes: bytes,
target_canvas_size: int = 2000,
fill_ratio: float = 0.85
) -> Image.Image:
"""
Standardisiert das Bild auf einer quadratischen weißen Leinwand mit 85%
Füllfaktor und erzeugt einen weichen Kontaktschatten.
"""
# 1. Freigestelltes Produkt laden
product = Image.open(io.BytesIO(transparent_png_bytes)).convert("RGBA")
prod_w, prod_h = product.size
# 2. Unter Beibehaltung des Seitenverhältnisses skalieren
max_dim = int(target_canvas_size * fill_ratio)
scale = min(max_dim / prod_w, max_dim / prod_h)
new_w, new_h = int(prod_w * scale), int(prod_h * scale)
product_resized = product.resize((new_w, new_h), Image.Resampling.LANCZOS)
# 3. Quadratische weiße Leinwand erstellen
canvas = Image.new("RGBA", (target_canvas_size, target_canvas_size), (255, 255, 255, 255))
# 4. Weichen Kontaktschatten generieren
alpha_mask = product_resized.split()[3]
shadow_height = max(10, int(new_h * 0.08))
# Alphamaske vertikal stauchen, um die Standfläche zu simulieren
shadow_footprint = alpha_mask.resize((new_w, shadow_height), Image.Resampling.BILINEAR)
shadow_footprint = shadow_footprint.filter(ImageFilter.GaussianBlur(radius=15))
# Dunkelgraue Schattenschicht mit reduzierter Deckkraft (35%)
shadow_layer = Image.new("RGBA", (new_w, shadow_height), (40, 40, 40, 0))
shadow_layer.putalpha(shadow_footprint.point(lambda p: int(p * 0.35)))
# 5. Elemente auf der Leinwand positionieren
pos_x = (target_canvas_size - new_w) // 2
pos_y = (target_canvas_size - new_h) // 2
# Schatten leicht versetzt am Boden platzieren
shadow_y = pos_y + new_h - int(shadow_height * 0.6)
canvas.paste(shadow_layer, (pos_x, shadow_y), shadow_layer)
# Produkt darüberlegen
canvas.paste(product_resized, (pos_x, pos_y), product_resized)
# In RGB konvertieren und zurückgeben
return canvas.convert("RGB")
def process_sku(raw_path: str, output_path: str):
with open(raw_path, "rb") as f:
raw_bytes = f.read()
# Schritt 1: Freistellen über API
cutout_bytes = remove_background(raw_bytes)
# Schritt 2: Bildstandardisierung und Schatten
final_img = standardize_product_image(cutout_bytes)
# Schritt 3: Als optimiertes JPEG speichern
final_img.save(output_path, "JPEG", quality=90, optimize=True)
5. Best Practices und Kostenoptimierung
- Nutzung von
mattingByUrlzur Bandbreiteneinsparung: Liegen Bilder bereits auf S3 oder Cloudflare R2, solltemattingByUrlverwendet werden. Durch die Übergabe der öffentlichen URL entfällt der Upload großer Binärdateien vom Applikationsserver. - Zweistufiger Freigabeprozess: Bei Lieferantenentwürfen empfiehlt sich die Voransicht mit
preview=true(0,25 Credits). Erst nach Freigabe und Veröffentlichung im Liveshop wird der 1-Credit-Aufruf in voller Auflösung ausgeführt. - Dauerhafte Speicherung transparenter PNGs: Speichern Sie die transparente Originaldatei aus Cutout.pro separat im Archiv. Sollten sich Marktplatzstandards künftig ändern (z. B. Wechsel zu Hellgrau oder veränderte Randabstände), lässt sich das gesamte Sortiment lokal neu zusammensetzen, ohne erneut kostenpflichtige API-Aufrufe zu tätigen.