Public API

Diese Seite ergänzt die OpenAPI UI um sofort nutzbare Requests, Beispiel-Responses und Hinweise zu stabilen Bild-URLs.

Schnellstart

Für die meisten Integrationen reichen diese vier Endpunkte.

Account
GET /user/profile

Liefert Profil, Limits und Nutzungswerte des Users.

Upload Session
POST /upload/sessions

Erstellt Upload-URL, Token und maximale Dateigröße.

Processing
GET /images/{uuid}/status

Zeigt, ob die Verarbeitung abgeschlossen oder fehlgeschlagen ist.

Finale Resource
GET /images/{uuid}

Liefert die finalen Bild- und Varianten-URLs.

1) Authentifizierung

Erstelle zuerst in den Benutzereinstellungen einen API-Schlüssel und sende ihn pro Request im Header X-API-Key.

export BASE_URL="https://pixelfox.cc"
export API_KEY="DEIN_API_KEY"

curl -sS "$BASE_URL/api/v1/user/profile" \
  -H "X-API-Key: $API_KEY" | jq

Alternative Header-Variante: Authorization: Bearer DEIN_API_KEY.

2) Upload-Session erzeugen

Vor jedem Upload wird ein zeitlich begrenztes Token ausgestellt. Zusätzlich kannst du pro Upload festlegen, welche Derivate erzeugt werden sollen. Das Original bleibt immer erhalten.

export FILE="./beispiel.jpg"
export FILE_SIZE=$(wc -c < "$FILE")

SESSION_JSON=$(curl -sS -X POST "$BASE_URL/api/v1/upload/sessions" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -d "{
    \"file_size\": $FILE_SIZE,
    \"processing\": {
      \"profile\": \"custom\",
      \"derivatives\": [
        { \"family\": \"webp\", \"size\": \"small\" },
        { \"family\": \"avif\", \"size\": \"small\" }
      ]
    }
  }")

echo "$SESSION_JSON" | jq
UPLOAD_URL=$(echo "$SESSION_JSON" | jq -r '.upload_url')
UPLOAD_TOKEN=$(echo "$SESSION_JSON" | jq -r '.token')

Lasse processing weg, wenn du die aktuellen User-Defaults verwenden willst. Mit profile=original_only wird nur das Original gespeichert.

Processing-Profile

ProfilVerhalten
defaultVerwendet die aktuellen User-Defaults aus den Einstellungen und friert sie für genau diese Upload-Session ein.
original_onlySpeichert nur das hochgeladene Original. Es werden keine zusätzlichen WebP-, AVIF- oder Original-Thumbnails erzeugt.
customErzeugt exakt die in derivatives angeforderten Derivate, sofern Plan und Admin-Settings sie erlauben.
// Gleichbedeutend mit den aktuellen User-Defaults
{ "file_size": 1837421 }

// Nur das Original behalten
{
  "file_size": 1837421,
  "processing": {
    "profile": "original_only"
  }
}

// Exakt kleine WebP- und AVIF-Varianten anfordern
{
  "file_size": 1837421,
  "processing": {
    "profile": "custom",
    "derivatives": [
      { "family": "webp", "size": "small" },
      { "family": "avif", "size": "small" }
    ]
  }
}

In Antworten kann bei älteren Bildern zusätzlich profile=legacy auftauchen. Das ist nur ein Rückwärtskompatibilitätswert für Uploads vor der neuen per-Request-Policy.

3) Bild hochladen und Resource abrufen

Lade die Datei per Multipart-Form an die upload_url aus Schritt 2 hoch. Anschließend prüfst du den Status und holst dir die finale Resource.

UPLOAD_RESULT=$(curl -sS -X POST "$UPLOAD_URL" \
  -H "Authorization: Bearer $UPLOAD_TOKEN" \
  -F "file=@$FILE")

echo "$UPLOAD_RESULT" | jq
IMAGE_UUID=$(echo "$UPLOAD_RESULT" | jq -r '.image_uuid')

curl -sS "$BASE_URL/api/v1/images/$IMAGE_UUID/status" \
  -H "X-API-Key: $API_KEY" | jq

curl -sS "$BASE_URL/api/v1/images/$IMAGE_UUID" \
  -H "X-API-Key: $API_KEY" | jq

Wiederhole den Status-Request, bis complete=true und failed=false zurückkommt.

Direkt nach dem Upload sind oft erst Original-Datei und ein Teil der Varianten verfügbar. Zusätzliche Derivate werden asynchron erzeugt.

Beispiel: GET /api/v1/user/profile

{
  "id": 42,
  "username": "pixelpete",
  "email": "[email protected]",
  "status": "active",
  "plan": "premium",
  "created_at": "2026-03-16T08:30:00Z",
  "last_login_at": "2026-03-16T09:12:44Z",
  "api_key_last_used_at": "2026-03-16T09:15:02Z",
  "stats": {
    "images": {
      "count": 128,
      "storage_used_bytes": 734003200,
      "storage_remaining_bytes": 2415919104
    },
    "albums": {
      "count": 7
    }
  },
  "limits": {
    "max_upload_bytes": 52428800,
    "storage_quota_bytes": 3149926400,
    "can_multi_upload": true,
    "image_upload_enabled": true,
    "direct_upload_enabled": true,
    "allowed_thumbnail_formats": ["original", "webp", "avif"]
  },
  "preferences": {
    "thumbnail_original": true,
    "thumbnail_webp": true,
    "thumbnail_avif": true
  }
}

Account-Daten, Limits und aktuelle Nutzung des authentifizierten Users.

Beispiel: POST /api/v1/upload/sessions

{
  "upload_url": "https://pixelfox.cc/api/v1/upload",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "pool_id": 2,
  "expires_at": 1773655200,
  "max_bytes": 52428800,
  "processing": {
    "profile": "custom",
    "keep_original": true,
    "derivatives": [
      { "family": "webp", "size": "small" },
      { "family": "avif", "size": "small" }
    ]
  }
}

Das Token ist nur kurz gültig, auf die Dateigröße begrenzt und trägt die konkrete Processing-Policy dieser Session.

Beispiel: Upload-Antwort

{
  "image_uuid": "fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8",
  "view_url": "/i/a1b2c3d4e5f6g7h8",
  "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/original.jpg",
  "stable_url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/original.jpg",
  "storage_url": "https://cdn.pixelfox.cc/uploads/original/2026/03/16/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8.jpg",
  "available_variants": ["original"],
  "processing": {
    "profile": "custom",
    "keep_original": true,
    "derivatives": [
      { "family": "webp", "size": "small" },
      { "family": "avif", "size": "small" }
    ]
  },
  "variants": {
    "original": {
      "original": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/original.jpg"
      }
    }
  },
  "stable_variants": {
    "original": {
      "original": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/original.jpg",
        "ready": true
      }
    },
    "webp": {
      "small": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/webp/small.webp",
        "ready": false
      }
    },
    "avif": {
      "small": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/avif/small.avif",
        "ready": false
      }
    }
  },
  "planned_variants": ["original", "webp", "avif"],
  "duplicate": false
}

Direkt nach dem Upload ist die Resource bereits adressierbar. Fertige Varianten erscheinen schrittweise in variants.

Beispiel: Status und finale Image-Resource

// GET /api/v1/images/{uuid}/status
{
  "complete": true,
  "failed": false,
  "view_url": "/i/a1b2c3d4e5f6g7h8"
}

// GET /api/v1/images/{uuid}
{
  "image_uuid": "fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8",
  "view_url": "/i/a1b2c3d4e5f6g7h8",
  "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/original.jpg",
  "stable_url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/original.jpg",
  "storage_url": "https://cdn.pixelfox.cc/uploads/original/2026/03/16/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8.jpg",
  "available_variants": ["original", "webp", "avif"],
  "processing": {
    "profile": "custom",
    "keep_original": true,
    "derivatives": [
      { "family": "webp", "size": "small" },
      { "family": "avif", "size": "small" }
    ]
  },
  "variants": {
    "original": {
      "original": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/original.jpg"
      }
    },
    "webp": {
      "small": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/webp/small.webp"
      }
    },
    "avif": {
      "small": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/avif/small.avif"
      }
    }
  },
  "stable_variants": {
    "original": {
      "original": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/original.jpg",
        "ready": true
      },
      "medium": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/medium.jpg",
        "ready": true
      },
      "small": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/original/small.jpg",
        "ready": true
      }
    },
    "webp": {
      "original": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/webp/original.webp",
        "ready": true
      },
      "medium": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/webp/medium.webp",
        "ready": true
      },
      "small": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/webp/small.webp",
        "ready": true
      }
    },
    "avif": {
      "medium": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/avif/medium.avif",
        "ready": false
      },
      "small": {
        "url": "https://pixelfox.cc/f/fd6b0a44-c4bb-4c95-8f48-31d5ec9cc4d8/avif/small.avif",
        "ready": false
      }
    }
  },
  "planned_variants": ["original", "webp", "avif"]
}

/status ist bewusst klein gehalten. Für alle fertigen URLs und Varianten verwendest du danach GET /api/v1/images/{uuid}.

PHP Beispiele

Für einfache Server-Integrationen reicht das PHP cURL-Extension vollkommen aus. Das erste Beispiel zeigt einen authentifizierten JSON-Request, das zweite den vollständigen Upload-Flow.

GET /api/v1/user/profile

<?php

$baseUrl = 'https://pixelfox.cc';
$apiKey = 'DEIN_API_KEY';

$ch = curl_init($baseUrl . '/api/v1/user/profile');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Accept: application/json',
        'X-API-Key: ' . $apiKey,
    ],
]);

$raw = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

if ($status !== 200) {
    throw new RuntimeException('API request failed: ' . $raw);
}

$profile = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
echo $profile['username'] . PHP_EOL;
echo $profile['limits']['max_upload_bytes'] . PHP_EOL;

Upload Flow mit Status-Polling

<?php

$baseUrl = 'https://pixelfox.cc';
$apiKey = 'DEIN_API_KEY';
$file = __DIR__ . '/beispiel.jpg';

function apiJson(string $method, string $url, string $apiKey, ?array $payload = null): array
{
    $headers = [
        'Accept: application/json',
        'X-API-Key: ' . $apiKey,
    ];

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_HTTPHEADER => $headers,
    ]);

    if ($payload !== null) {
        $headers[] = 'Content-Type: application/json';
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_THROW_ON_ERROR));
    }

    $raw = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);

    return [
        'status' => $status,
        'body' => json_decode($raw, true, 512, JSON_THROW_ON_ERROR),
    ];
}

$session = apiJson('POST', $baseUrl . '/api/v1/upload/sessions', $apiKey, [
    'file_size' => filesize($file),
]);

$upload = curl_init($session['body']['upload_url']);
curl_setopt_array($upload, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $session['body']['token'],
    ],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile($file),
    ],
]);

$uploadRaw = curl_exec($upload);
curl_close($upload);

$uploadResult = json_decode($uploadRaw, true, 512, JSON_THROW_ON_ERROR);
$imageUuid = $uploadResult['image_uuid'];

do {
    sleep(1);
    $status = apiJson('GET', $baseUrl . '/api/v1/images/' . $imageUuid . '/status', $apiKey);
} while (!$status['body']['complete'] && !$status['body']['failed']);

if ($status['body']['failed']) {
    throw new RuntimeException('Image processing failed');
}

$image = apiJson('GET', $baseUrl . '/api/v1/images/' . $imageUuid, $apiKey);
echo $image['body']['url'] . PHP_EOL;

Konsistente Bild-URLs verstehen

PixelFox liefert bewusst zwei URL-Typen aus. Damit kannst du wahlweise stabile öffentliche Links verwenden oder direkt auf die aktuelle Storage-Adresse zugreifen.

FeldBedeutung
view_urlRelative URL zur HTML-Ansicht der Bildseite, zum Beispiel /i/abc123....
urlPrimäre öffentliche Bild-URL. In der Regel identisch zu stable_url und für Embeds, Hotlinks und API-Consumer die beste Standardwahl.
stable_urlStabile /f/{uuid}/...-Adresse. Diese URL bleibt konsistent, auch wenn sich die interne Storage-Struktur oder das Zielsystem später ändert.
variantsNur die aktuell fertigen Varianten mit stabilen öffentlichen URLs.
processingDie effektive Processing-Policy dieses Uploads. Dort siehst du, ob der Upload mit default, original_only oder custom erstellt wurde und welche Derivate konkret dazugehören.
stable_variantsVorhersagbare stabile Variant-URLs inklusive ready-Flag. Damit kannst du feste URLs vorhalten und trotzdem erkennen, ob die Datei schon existiert.
storage_urlDirekte aktuelle Storage-URL der Originaldatei. Praktisch für Debugging oder interne Tools, aber weniger zukunftssicher als stable_url.
storage_variantsDirekte Storage-URLs aller bereits erzeugten Varianten. Gleiches Prinzip wie storage_url.
planned_variantsWelche Variant-Familien für dieses Bild laut gespeicherter Processing-Policy grundsätzlich vorgesehen sind.

Empfehlung für Integrationen

Verwende standardmäßig url oder die Einträge aus variants. Wenn du mit noch nicht fertigen Derivaten planst, nimm stable_variants und prüfe das jeweilige ready-Flag.

Wichtiger Unterschied

/f/... ist eine stabile öffentliche Adresse, die auf die aktuelle Datei weiterleitet. /uploads/... oder CDN-Pfade können sich dagegen mit Storage-Pools, Migrationen oder künftigen Infrastruktur-Änderungen ändern.

OpenAPI