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.
Liefert Profil, Limits und Nutzungswerte des Users.
Erstellt Upload-URL, Token und maximale Dateigröße.
Zeigt, ob die Verarbeitung abgeschlossen oder fehlgeschlagen ist.
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" | jqAlternative 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. Mit album_id kannst du den Upload direkt in ein bestehendes eigenes Album einsortieren. Mit is_nsfw markierst du den Upload als sensiblen Inhalt. Mit is_ai_generated kennzeichnest du ihn als KI-generiert.
export FILE="./beispiel.jpg"
export FILE_SIZE=$(wc -c < "$FILE")
export ALBUM_ID=42
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,
\"album_id\": $ALBUM_ID,
\"is_nsfw\": true,
\"is_ai_generated\": true,
\"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. Lasse album_id weg, wenn der Upload keinem Album zugeordnet werden soll. Lasse is_nsfw weg, um den NSFW-Default aus deinen Einstellungen zu verwenden, oder setze es explizit auf false bzw. true für diesen Upload. is_ai_generated funktioniert genauso mit dem KI-Default.
Processing-Profile
| Profil | Verhalten |
|---|---|
| default | Verwendet die aktuellen User-Defaults aus den Einstellungen und friert sie für genau diese Upload-Session ein. |
| original_only | Speichert nur das hochgeladene Original. Es werden keine zusätzlichen WebP-, AVIF- oder Original-Thumbnails erzeugt. |
| custom | Erzeugt exakt die in derivatives angeforderten Derivate, sofern Plan und Admin-Settings sie erlauben. |
// Gleichbedeutend mit den aktuellen User-Defaults
{ "file_size": 1837421 }
// In ein bestehendes Album hochladen
{
"file_size": 1837421,
"album_id": 42,
"is_nsfw": true,
"is_ai_generated": true
}
// 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" | jqWiederhole 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": {
"upload_nsfw_by_default": false,
"upload_ai_generated_by_default": false,
"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,
"album_id": 42,
"is_nsfw": true,
"is_ai_generated": true,
"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. Wenn album_id zurückkommt, ist die Session an dieses Album gebunden. is_nsfw zeigt an, ob der Upload als sensibel markiert wurde. is_ai_generated zeigt die KI-Markierung.
Ist das Speicherkontingent voll, antworten Session und direkter Upload mit 413 und quota_exceeded. Gezählt werden Originaldateien und erzeugte Varianten. Die Antwort nennt freien Rest, benötigte Größe und das aktuelle Kontingent. Free sieht darin Premium mit 200 GB und Premium Max mit 1000 GB, Premium nur noch Premium Max.
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",
"is_nsfw": true,
"is_ai_generated": true,
"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",
"is_nsfw": true,
"is_ai_generated": true,
"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),
'album_id' => 42,
'is_nsfw' => true,
'is_ai_generated' => true,
]);
$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.CC liefert bewusst zwei URL-Typen aus. Damit kannst du wahlweise stabile öffentliche Links verwenden oder direkt auf die aktuelle Storage-Adresse zugreifen.
| Feld | Bedeutung |
|---|---|
| view_url | Relative URL zur HTML-Ansicht der Bildseite, zum Beispiel /i/abc123.... |
| url | Primäre öffentliche Bild-URL. In der Regel identisch zu stable_url und für Embeds, Hotlinks und API-Consumer die beste Standardwahl. |
| stable_url | Stabile /f/{uuid}/...-Adresse. Diese URL bleibt konsistent, auch wenn sich die interne Storage-Struktur oder das Zielsystem später ändert. |
| variants | Nur die aktuell fertigen Varianten mit stabilen öffentlichen URLs. |
| processing | Die 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_variants | Vorhersagbare stabile Variant-URLs inklusive ready-Flag. Damit kannst du feste URLs vorhalten und trotzdem erkennen, ob die Datei schon existiert. |
| storage_url | Direkte aktuelle Storage-URL der Originaldatei. Praktisch für Debugging oder interne Tools, aber weniger zukunftssicher als stable_url. |
| storage_variants | Direkte Storage-URLs aller bereits erzeugten Varianten. Gleiches Prinzip wie storage_url. |
| planned_variants | Welche 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.
