API-Dokumentation

PhotoFig-API

Stelle Produktbild-Bearbeitungen und Größenänderungen in die Warteschlange, wende Vorlagen auf ganze Stapel an, verfolge den Fortschritt und erhalte signierte Webhook-Ereignisse mit API-Schlüsseln.

Benötigen Sie ein maschinenlesbares Schema? OpenAPI-JSON herunterladen.

Auf dieser Seite

Schnellstart

Erstellen Sie einen API-Schlüssel unter Einstellungen. Ersetzen Sie unten YOUR_API_KEY und speichern Sie ein Foto als product.jpg.

  1. Foto senden

    Laden Sie das Foto hoch, um einen Produktschatten hinzuzufügen. Die Antwort enthält eine Job-ID und statusUrl.

    curl https://api.photofig.com/v1/tools/ai-shadows/edit \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -F "image=@product.jpg"
  2. Job prüfen

    Ersetzen Sie STATUS_URL durch die zurückgegebene statusUrl. Bei queued oder processing warten Sie, bevor Sie erneut prüfen.

    curl "STATUS_URL" \
      -H "Authorization: Bearer YOUR_API_KEY"
  3. Ergebnis herunterladen

    Sobald status den Wert completed hat, ersetzen Sie RESULT_URL durch die zurückgegebene resultUrl, um das Bild zu speichern.

    curl -fL "RESULT_URL" -o photofig-result.png

Mit Webhooks erhalten Sie Abschlussmeldungen automatisch.

Authentifizierung

API-Routen akzeptieren API-Schlüssel aus den Einstellungen. Der vollständige geheime Schlüssel wird nur einmal bei der Erstellung angezeigt.

Authorization: Bearer pf_live_...

API-Schlüssel funktionieren nur mit den Endpunkten auf dieser Seite; alle anderen PhotoFig-Routen lehnen sie ab. Ein Schlüssel handelt für die Person, die ihn erstellt hat, in dem Workspace, in dem er erstellt wurde.

Limits und Kontingente

API-Zugriff ist in Pro und Studio enthalten. GET /v1/account zeigt die Limits Ihres Plans, darunter das stündliche Anfragekontingent in limits.rateLimitPerHour.

Jede authentifizierte Anfrage zählt zum stündlichen Kontingent, auch das Abfragen des Jobstatus. Antworten enthalten X-RateLimit-Limit und X-RateLimit-Remaining. Ist das Kontingent aufgebraucht, antwortet die API mit 429 rate_limit_exceeded und einem Retry-After-Header.

mask verbraucht Hintergrundentfernungen, ai-bg und ai-shadows je einen KI-Credit, resize keines von beidem. Credits werden erst berechnet, wenn ein Job abgeschlossen ist.

Wartende und laufende Jobs zählen zum Parallel-Limit Ihres Plans. Darüber hinaus erhalten neue Bearbeitungen 429 too_many_jobs, bis frühere Jobs fertig sind.

POST /v1/uploads und POST /v1/tools/{tool_id}/edit akzeptieren einen optionalen X-Idempotency-Key-Header. Ein erneuter Versuch mit demselben Schlüssel liefert die erste Antwort, statt einen zweiten Job zu starten. Verwenden Sie daher für jede neue Anfrage einen neuen Schlüssel.

Konto

GET/v1/account

Mit dieser Route können Sie Ihre Zugangsdaten prüfen und Planlimits, verbleibende KI-Credits sowie verfügbare Tools abrufen.

{
  "accountId": "uuid",
  "workspaceId": "uuid",
  "plan": "pro",
  "apiEnabled": true,
  "credits": {
    "remaining": 2000,
    "bonusRemaining": 0,
    "periodEndsAt": "2026-11-01T00:00:00Z"
  },
  "limits": {
    "maxFileSizeBytes": 10485760,
    "rateLimitPerHour": 60,
    "concurrentJobs": 3,
    "maxApiKeys": 1,
    "freeBgRemovals": 0,
    "bgRemovalsUsed": 0,
    "aiCredits": 2000
  },
  "tools": [
    "mask",
    "ai-bg",
    "ai-shadows",
    "resize"
  ]
}

Tools

GET/v1/tools
GET/v1/tools/{tool_id}

Jedes Tool akzeptiert ein normales Produktbild per imageUrl, uploadSessionId oder Multipart-Upload. mask müssen Sie nicht zuerst aufrufen: ai-bg und ai-shadows entfernen den Hintergrund selbst.

mask

Entfernt den Hintergrund und gibt einen transparenten PNG-Ausschnitt zurück. Verwenden Sie dieses Tool, wenn Sie das Produkt für Ihr eigenes Compositing oder eine Marktplatz-Integration freistellen möchten.

ai-shadows

Fügt einen realistischen Produktschatten hinzu und gibt ein Bild zurück, das auf einem sauberen Hintergrund platziert werden kann. Funktioniert am besten bei Produktfotos, auf denen das Motiv klar erkennbar und nicht von einer unruhigen Szene verdeckt ist.

ai-bg

Erstellt einen neuen Produkthintergrund aus einem kurzen Thema, zum Beispiel warm oak tabletop oder minimal white studio. Senden Sie das Produktbild direkt; ein separater Aufruf zur Hintergrundentfernung ist nicht erforderlich.

resize

Passt ein Foto auf eine exakte Leinwandgröße an und behält seinen eigenen Hintergrund, wie „Fotogröße ändern“ in der App. Wählen Sie Einpassen oder Füllen, die Position und die Füllfarbe. Verbraucht keine KI-Credits.

In einem Aufruf hochladen und bearbeiten

POST/v1/tools/{tool_id}/edit

Dies ist der einfachste Weg: Senden Sie eine Bearbeitung mit imageUrl, wenn das Quellbild bereits über eine URL erreichbar ist, oder übertragen Sie eine lokale Datei als Multipart-Feld image. Diese Variante eignet sich, wenn Sie genau ein Tool auf ein Bild anwenden möchten.

Wählen Sie diese Option, wenn Sie ein Bild haben, es nur einmal bearbeiten müssen und die hochgeladene Quelle nicht wiederverwendet werden muss.

curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
  -H "Authorization: Bearer pf_live_..." \
  -F "image=@product.jpg" \
  -F "seed=128742"

Zuerst hochladen, später bearbeiten

POST/v1/uploads

Erstellen Sie eine Upload-Session, um die Bilddaten direkt in den Speicher zu senden, und starten Sie dann eine Bearbeitung mit der zurückgegebenen uploadSessionId. Es gilt dieselbe Größenbegrenzung wie bei einer Multipart-Anfrage, und jede Session wird für eine Bearbeitung verwendet.

Wählen Sie diesen Weg, wenn Ihr Client das Bild nicht über die Bearbeitungsanfrage senden soll, etwa ein Browser, der direkt in den Speicher hochlädt.

UPLOAD_JSON=$(curl -s -X POST https://api.photofig.com/v1/uploads \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "contentType": "image/jpeg",
    "filename": "product.jpg",
    "sizeBytes": 1842031
  }')

curl -X PUT "$(echo "$UPLOAD_JSON" | jq -r '.uploadUrl')" \
  -H "Content-Type: image/jpeg" \
  --data-binary @product.jpg

curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d "{
    \"uploadSessionId\": \"$(echo "$UPLOAD_JSON" | jq -r '.uploadSessionId')\",
    \"parameters\": { \"seed\": 128742 }
  }"

Bearbeitungen erstellen

POST/v1/tools/{tool_id}/edit

Senden Sie Bearbeitungen mit imageUrl, uploadSessionId oder einem Multipart-Feld image. Die Antwort enthält eine Job-ID für Statusabfrage, Abbruch, Löschung und die Zuordnung von Webhook-Ereignissen. Parameter, die ein Tool nicht verwendet, werden ignoriert.

KI-Hintergrund

Der Endpunkt für KI-Hintergründe funktioniert am besten mit einem prägnanten Szenenthema: einer Umgebung, Oberfläche, Lichtstimmung oder Atmosphäre in wenigen Worten. Gute Beispiele sind: warm oak tabletop,minimal white studio, and soft morning kitchen light.

curl -X POST https://api.photofig.com/v1/tools/ai-bg/edit \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "imageUrl": "https://cdn.example.com/product.png",
    "parameters": {
      "theme": "warm oak tabletop",
      "seed": 128742
    }
  }'

Product Shadow

curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "imageUrl": "https://cdn.example.com/product.png",
    "parameters": { "seed": 128742 }
  }'

Hintergrundentfernung

mask hat keine Parameter und liefert einen PNG-Freisteller mit Transparenz.

curl -X POST https://api.photofig.com/v1/tools/mask/edit \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "imageUrl": "https://cdn.example.com/product.png"
  }'

Größe anpassen

width und height legen die Ausgabe in Pixeln fest, von 100 bis 4096. mode ist fit (das ganze Foto, Standard), fill (füllt die Leinwand und beschneidet den Überstand), width oder height. horizontal und vertical positionieren das Foto, und background füllt den freien Raum: transparent, eine #RRGGBB-Farbe oder ein Verlaufsobjekt. Das Ergebnis ist ein PNG.

curl -X POST https://api.photofig.com/v1/tools/resize/edit \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "imageUrl": "https://cdn.example.com/product.jpg",
    "parameters": {
      "width": 1000,
      "height": 1000,
      "mode": "fit",
      "background": "#ffffff"
    }
  }'

Jobs

GET/v1/jobs
GET/v1/jobs/{job_id}
POST/v1/jobs/{job_id}/cancel
DELETE/v1/jobs/{job_id}

API-Jobs auflisten, abfragen, abbrechen oder löschen. API-Jobs werden nicht unter den Uploads oder Designs in der App angezeigt. Beim Löschen werden jedoch alle zugehörigen API-Dateien entfernt.

GET /v1/jobs/{job_id} liefert den Status des Jobs. Ist er abgeschlossen, laden Sie das Bild über resultUrl vor expiresAt herunter. Jede Statusabfrage zählt zu Ihrem stündlichen Kontingent; nutzen Sie Webhooks für Abschlussmeldungen.

{
  "id": "api_edit_uuid",
  "tool": "ai-shadows",
  "status": "completed",
  "createdAt": "2026-07-15T10:15:00Z",
  "startedAt": "2026-07-15T10:15:04Z",
  "finishedAt": "2026-07-15T10:15:23Z",
  "statusUrl": "https://api.photofig.com/v1/jobs/api_edit_uuid",
  "resultUrl": "https://storage.example.com/signed-result-url",
  "thumbnailUrl": "https://storage.example.com/signed-thumbnail-url",
  "expiresAt": "2026-07-15T11:15:23Z",
  "error": null
}

Vorlagen

GET/v1/templates
POST/v1/templates
GET/v1/templates/{template_id}
PATCH/v1/templates/{template_id}
DELETE/v1/templates/{template_id}

Eine Vorlage ist ein Look, den du auf viele Fotos anwendest: Hintergrund entfernen, Platzierung, Hintergrund und Schatten, Abstand und die Exportgrößen. Über die API erstellte Vorlagen lassen sich in der PhotoFig-App öffnen und bearbeiten, und umgekehrt. Systemvorlagen sind sofort nutzbar und schreibgeschützt.

mask und resize sind Pflicht; die übrigen Schritte sind optional und laufen in fester Reihenfolge. Unbekannte Schritte oder Felder werden abgelehnt, und Werte müssen in den Bereichen liegen, die der Editor anbietet. Das OpenAPI-Schema führt jedes Feld auf.

curl -X POST https://api.photofig.com/v1/templates \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Cream catalog",
    "steps": {
      "mask": {},
      "reposition": { "horizontal": "center", "vertical": "center", "scale": 0.85 },
      "background": { "backgroundType": "solid", "color": "#f6f1ea" },
      "ai-shadows": { "opacity": 0.8 },
      "resize": { "mode": "fit", "targets": [{ "width": 2000, "height": 2000 }] }
    },
    "export": { "format": "jpg", "background": "#ffffff" }
  }'

creditsPerPhoto ist das, was die Vorlage pro Foto berechnet, zum Beispiel ein KI-Credit für ai-shadows.

Stapel

POST/v1/batches
POST/v1/batches/{batch_id}/uploads
POST/v1/batches/{batch_id}/uploads/{upload_id}/complete
POST/v1/batches/{batch_id}/process
GET/v1/batches/{batch_id}
GET/v1/batches
POST/v1/batches/{batch_id}/cancel
DELETE/v1/batches/{batch_id}

Ein Stapel wendet eine Vorlage auf viele Fotos an. Lege ihn an, füge die Fotos hinzu und verarbeite ihn dann mit einer Vorlage. Fotos behalten die Position, die du ihnen gibst.

Jedes Foto geht direkt in den Speicher: Fordere einen Upload an, sende die Bytes per PUT an uploadUrl und schließe ihn dann ab.

BATCH_ID=$(curl -s -X POST https://api.photofig.com/v1/batches \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "Spring arrivals" }' | jq -r '.id')

# For each photo: ask for an upload, PUT the bytes, complete it.
UPLOAD=$(curl -s -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/uploads" \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "filename": "boots.jpg", "contentType": "image/jpeg", "sizeBytes": 1842031, "position": 0 }')
curl -X PUT "$(echo "$UPLOAD" | jq -r '.uploadUrl')" \
  -H "Content-Type: image/jpeg" --data-binary @boots.jpg
curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/uploads/$(echo "$UPLOAD" | jq -r '.uploadId')/complete" \
  -H "Authorization: Bearer pf_live_..."

curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/process" \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "templateId": "TEMPLATE_ID" }'

Erfahren, wann ein Stapel fertig ist

Registriere einmal einen Webhook für batch.completed, statt abzufragen. PhotoFig ruft ihn auf, sobald ein Stapel fertig ist, mit der Stapel-ID und wie viele Fotos gelungen oder fehlgeschlagen sind.

curl -X POST https://api.photofig.com/v1/webhooks \
  -H "Authorization: Bearer pf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/photofig/webhooks",
    "events": ["batch.completed"]
  }'
{
  "event": "batch.completed",
  "eventId": "uuid",
  "createdAt": "2026-10-06T12:00:00Z",
  "data": {
    "batchId": "uuid",
    "status": "completed",
    "totalItems": 12,
    "completedItems": 12,
    "failedItems": 0
  }
}

Wenn batch.completed eintrifft, lies den Stapel. Jedes fertige Foto hat einen Vorschaulink mit bis zu 1024 Pixeln. Hintergrundentfernungen und KI-Credits werden wie in der App berechnet.

{
  "id": "uuid",
  "name": "Spring arrivals",
  "status": "completed",
  "templateName": "Cream catalog",
  "totalItems": 2,
  "completedItems": 2,
  "failedItems": 0,
  "resultsAvailableUntil": "2026-10-20T12:00:00Z",
  "items": [
    {
      "id": "uuid",
      "position": 0,
      "filename": "boots.jpg",
      "status": "completed",
      "width": 3024,
      "height": 4032,
      "preview": {
        "url": "https://...",
        "width": 1024,
        "height": 1024
      }
    }
  ]
}

Ergebnisse herunterladen

GET/v1/batches/{batch_id}/items/{item_id}/download
GET/v1/batches/{batch_id}/download-url

Lade jedes Ergebnis in voller Größe im Exportformat der Vorlage herunter oder den ganzen Stapel als ZIP. Jedes Ergebnis zählt einmal als Export, wie in der App; erneutes Herunterladen ist kostenlos.

Ergebnisse teilen

POST/v1/batches/{batch_id}/share
GET/v1/batches/{batch_id}/share
DELETE/v1/batches/{batch_id}/share

Ein Freigabelink ist eine öffentliche Seite mit Vorher-Nachher-Vorschauen und ZIP-Download, ohne Anmeldung. Ein Stapel hat einen Link: Eine erneute Anfrage liefert denselben, und Widerrufen beendet ihn sofort. Downloads von der Seite zählen als deine Exporte, und die Seite funktioniert bis availableUntil. Teilen erfordert einen kostenpflichtigen Plan.

curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/share" \
  -H "Authorization: Bearer pf_live_..."
{
  "url": "https://photofig.com/share/TOKEN",
  "availableUntil": "2026-10-20T12:00:00Z",
  "createdAt": "2026-10-06T12:05:00Z",
  "downloadCount": 0
}

Webhooks

Mit Webhooks teilt PhotoFig deinem Server mit, wenn ein API-Job fertig ist, fehlschlägt oder abgebrochen wird und wenn ein Stapel fertig ist, sodass dein Backend nicht abfragen muss. Registriere eine HTTPS-URL auf einem öffentlichen Host. Ein Endpunkt erhält Ereignisse für Jobs und Stapel, die mit den API-Schlüsseln seines Besitzers erstellt wurden.

GET/v1/webhooks
POST/v1/webhooks
GET/v1/webhooks/{webhook_id}
PATCH/v1/webhooks/{webhook_id}
DELETE/v1/webhooks/{webhook_id}
POST/v1/webhooks/{webhook_id}/test

Unterstützte Ereignisse sind webhook.test,job.completed,job.failed,job.cancelled, und batch.completed. Job-Ereignisse verwenden die Job-ID, die beim Erstellen der Bearbeitung zurückgegeben wird; batch.completed enthält die Stapel-ID.

{
  "event": "job.completed",
  "eventId": "uuid",
  "createdAt": "2026-07-15T10:15:23Z",
  "data": {
    "id": "api_edit_uuid",
    "tool": "ai-shadows",
    "status": "completed",
    "resultUrl": "https://storage.example.com/signed-result-url",
    "thumbnailUrl": "https://storage.example.com/signed-thumbnail-url",
    "expiresAt": "2026-07-15T11:15:23Z"
  }
}

Jede Zustellung prüfen

Jede Anfrage enthält PhotoFig-Webhook-Timestamp und PhotoFig-Webhook-Signature. Berechnen Sie mit dem Secret des Endpunkts einen HMAC-SHA256 aus dem Zeitstempel, einem Punkt und dem unveränderten Anfragetext und vergleichen Sie ihn mit dem Wert nach v1=. Lehnen Sie Zeitstempel ab, die älter als einige Minuten sind. Das Secret wird nur beim Erstellen des Endpunkts angezeigt.

import crypto from 'node:crypto';

// rawBody is the request body exactly as received, before JSON parsing.
export function verifyPhotoFigWebhook(headers, rawBody, secret) {
  const timestamp = headers['photofig-webhook-timestamp'];
  const signature = headers['photofig-webhook-signature'] ?? '';
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected = 'v1=' + crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex');
  return signature.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Antworten Sie innerhalb von 10 Sekunden mit einem beliebigen 2xx-Status. Andere Antworten werden nach 1 Minute, 5 Minuten, 30 Minuten, 2 Stunden und 12 Stunden erneut zugestellt. PhotoFig-Webhook-Id bleibt bei Wiederholungen gleich, damit Sie Duplikate überspringen können. Download-Links im Payload werden für jeden Versuch neu signiert und funktionieren nicht mehr, sobald das Ergebnis abläuft.

Fehler

Fehlerantworten enthalten einen stabilen maschinenlesbaren Code und eine verständliche Meldung. Verwenden Sie den Code für Verzweigungen in Ihrer Client-Logik.

{
  "code": "invalid_request",
  "message": "imageUrl or uploadSessionId is required"
}

Häufige Codes

invalid_request
Ein Parameter fehlt oder ist ungültig; die Meldung nennt ihn.
api_key_not_allowed
Ein API-Schlüssel wurde auf einer Route außerhalb der öffentlichen API verwendet.
api_access_disabled
Der Plan des Workspace enthält keinen API-Zugriff.
insufficient_funds
Für dieses Tool sind keine KI-Credits oder Hintergrundentfernungen mehr übrig.
rate_limit_exceeded
Das stündliche Anfragekontingent ist aufgebraucht; warten Sie Retry-After ab.
too_many_jobs
Zu viele Jobs warten oder laufen; versuchen Sie es erneut, wenn frühere fertig sind.
tool_unavailable
Die Worker des Tools sind kurz nicht verfügbar; versuchen Sie es gleich erneut.
webhook_limit_reached
Der Inhaber des Schlüssels hat die Höchstzahl an Webhook-Endpunkten für diesen Workspace erreicht.

Aufbewahrung der Ergebnisse

Abgeschlossene API-Jobs bleiben über GET /v1/jobs und GET /v1/jobs/{job_id} sichtbar. Die Statusantwort enthält signierte resultUrl- und thumbnailUrl-Links, solange die Ergebnisse verfügbar sind.

API-Dateien werden getrennt von interaktiven Uploads und Designs gespeichert. Sie werden nicht in der App-Bibliothek angezeigt.

API-Jobdaten sowie zugehörige Eingabe-, Ergebnis- und Vorschaudateien werden nach Abschluss, Fehlschlag oder Abbruch eine Stunde lang aufbewahrt. Das Feld „expiresAt“ zeigt bei abgeschlossenen Jobs den geplanten Löschzeitpunkt an.

Verwenden Sie DELETE /v1/jobs/{job_id}, nachdem Sie nicht mehr benötigte Ergebnisse heruntergeladen haben. Damit wird unfertige Arbeit nach Möglichkeit abgebrochen und der Jobeintrag samt API-eigenen Dateien vor der automatischen Bereinigung gelöscht.