REST API v1

API Reference

Integrate UltraPixx image intelligence directly into your applications. Analyze, optimize, convert, and run the full processing pipeline via a simple REST API.

key

Authentication

All authenticated endpoints require an API key. You can obtain your API key from your account settings page.

Pass the key using either of these headers:

HTTP Headers
Authorization: Bearer <your_api_key>
-- or --
X-API-Key: <your_api_key>
info

Keep your API key secret. Never expose it in client-side JavaScript or public repositories.

speed

Rate Limits

Requests are limited to 60 requests per minute per API key. When the limit is exceeded, the API returns:

429 Too Many Requests
{
  "message": "Too Many Attempts.",
  "retry_after": 30
}
link

Base URL

https://ultrapixx.com/api/v1

All endpoints below are relative to this base URL.

GET /languages No auth required

Returns the list of languages supported for AI-generated SEO metadata (filenames & alt-text).

Success Response β€” 200 OK

JSON
{
  "data": [
    { "code": "de", "name": "German",  "native_name": "Deutsch" },
    { "code": "en", "name": "English", "native_name": "English" },
    { "code": "fr", "name": "French",  "native_name": "FranΓ§ais" }
  ]
}

Code Samples

curl https://ultrapixx.com/api/v1/languages
$response = Http::get("https://ultrapixx.com/api/v1/languages");
$languages = $response->json("data");
POST /images/analyze API Key required

Upload an image. The API dispatches an AI job to generate an SEO-optimized filename and descriptive alt-text. Returns immediately with a job_id β€” poll GET /jobs/{id} for results.

Request β€” multipart/form-data

Field Type Required Description
imagefileYesImage file (max 10 MB). Accepted: JPEG, PNG, GIF, WebP.
languagesstring[]NoISO 639-1 codes, e.g. ["en","de"]. Defaults to ["en"].
project_idstringNoExisting project ULID. Creates an "API Uploads" project if omitted.
project_namestringNoCustom project name (used when project_id is not provided).

Success Response β€” 202 Accepted

{
  "data": {
    "job_id": "01hwz3p4kj0000000000000000",
    "status": "pending",
    "message": "Analysis dispatched. Poll GET /api/v1/jobs/01hwz3p4kj0000000000000000 for results."
  }
}

Code Samples

curl -X POST https://ultrapixx.com/api/v1/images/analyze \
  -H "Authorization: Bearer $API_KEY" \
  -F "image=@photo.jpg" \
  -F "languages[]=en" \
  -F "languages[]=de"
$response = Http::withToken($apiKey)
    ->attach("image", file_get_contents("photo.jpg"), "photo.jpg")
    ->post("https://ultrapixx.com/api/v1/images/analyze", [
        "languages" => ["en", "de"],
    ]);

$jobId = $response->json("data.job_id");
POST /images/optimize API Key required

Upload an image and dispatch a TinyPNG compression job. Once complete, download the result via GET /images/{id}/optimized.

Request β€” multipart/form-data

Field Type Required Description
imagefileYesImage file (max 10 MB).
project_idstringNoExisting project ULID.
project_namestringNoCustom project name.

Success Response β€” 202 Accepted

{
  "data": {
    "job_id": "01hwz3p4kj0000000000000000",
    "status": "pending",
    "message": "Optimization dispatched. Poll GET /api/v1/jobs/01hwz3p4kj0000000000000000 for results."
  }
}

Code Samples

curl -X POST https://ultrapixx.com/api/v1/images/optimize \
  -H "Authorization: Bearer $API_KEY" \
  -F "image=@photo.jpg"
$response = Http::withToken($apiKey)
    ->attach("image", file_get_contents("photo.jpg"), "photo.jpg")
    ->post("https://ultrapixx.com/api/v1/images/optimize");

$jobId = $response->json("data.job_id");
POST /images/convert API Key required

Upload an image and dispatch a format conversion job (PNG/JPEG β†’ WebP or AVIF).

Request β€” multipart/form-data

Field Type Required Description
imagefileYesImage file (max 10 MB).
formatstringNoTarget format: webp (default) or avif.
project_idstringNoExisting project ULID.
project_namestringNoCustom project name.

Success Response β€” 202 Accepted

{
  "data": {
    "job_id": "01hwz3p4kj0000000000000000",
    "status": "pending",
    "message": "Conversion dispatched. Poll GET /api/v1/jobs/01hwz3p4kj0000000000000000 for results."
  }
}

Code Samples

curl -X POST https://ultrapixx.com/api/v1/images/convert \
  -H "Authorization: Bearer $API_KEY" \
  -F "image=@photo.jpg" \
  -F "format=avif"
$response = Http::withToken($apiKey)
    ->attach("image", file_get_contents("photo.jpg"), "photo.jpg")
    ->post("https://ultrapixx.com/api/v1/images/convert", [
        "format" => "avif",
    ]);

$jobId = $response->json("data.job_id");
POST /images/process API Key required

Full pipeline: analyze + optimize + convert in a single call. The API dispatches all three jobs concurrently. Poll GET /jobs/{id} until status is completed.

Request β€” multipart/form-data

Field Type Required Description
imagefileYesImage file (max 10 MB).
languagesstring[]NoISO 639-1 codes. Defaults to ["en"].
formatstringNoTarget format: webp (default) or avif.
project_idstringNoExisting project ULID.
project_namestringNoCustom project name.

Success Response β€” 202 Accepted

{
  "data": {
    "job_id": "01hwz3p4kj0000000000000000",
    "status": "pending",
    "message": "Processing dispatched. Poll GET /api/v1/jobs/01hwz3p4kj0000000000000000 for results."
  }
}

Code Samples

curl -X POST https://ultrapixx.com/api/v1/images/process \
  -H "Authorization: Bearer $API_KEY" \
  -F "image=@photo.jpg" \
  -F "languages[]=en" \
  -F "languages[]=de" \
  -F "format=webp"
$response = Http::withToken($apiKey)
    ->attach("image", file_get_contents("photo.jpg"), "photo.jpg")
    ->post("https://ultrapixx.com/api/v1/images/process", [
        "languages" => ["en", "de"],
        "format"    => "webp",
    ]);

$jobId = $response->json("data.job_id");
GET /credits/afford API Key required

Lightweight pre-flight check: will the authenticated user have enough credits to run the full pipeline on N images? No image upload required. Useful for surfacing "not enough credits" messaging before the user commits to the upload.

Query Parameters

Name Type Description
imagesinteger (1–100)Required. Number of images you intend to process.
languagesinteger (1–10)Optional. How many alt-text languages per image. Defaults to 1.
formatstringOptional. Conversion target: webp (default) or avif.

Success Response β€” 200 OK

{
  "data": {
    "can_afford": true,
    "required": 50,
    "balance": 1200,
    "shortfall": 0
  }
}

Code Samples

curl "https://ultrapixx.com/api/v1/credits/afford?images=5&languages=2&format=webp" \
  -H "Authorization: Bearer $API_KEY"
$response = Http::withToken($apiKey)
    ->get("https://ultrapixx.com/api/v1/credits/afford", [
        "images"    => 5,
        "languages" => 2,
        "format"    => "webp",
    ]);

if (! $response->json("data.can_afford")) {
    throw new RuntimeException("Short " . $response->json("data.shortfall") . " credits");
}
GET /credits/balance API Key required

Returns the current credit balance for the authenticated account. Primarily used by the bundled WordPress plugin to show live credits on its settings page, but available to any integration that wants to display balance.

Success Response β€” 200 OK

{
  "data": {
    "balance": 1200
  }
}

Code Samples

curl https://ultrapixx.com/api/v1/credits/balance \
  -H "Authorization: Bearer $API_KEY"
$balance = Http::withToken($apiKey)
    ->get("https://ultrapixx.com/api/v1/credits/balance")
    ->json("data.balance");
GET /jobs/{id} API Key required

Poll the status of an async image processing job. Use the job_id returned by any of the dispatch endpoints. When status is "completed", all results are included in the response.

Job Status Values

pending

Queued

analyzing

AI running

optimizing

TinyPNG running

converting

Format conversion

completed

All jobs done

failed

Error

Note: /images/process fans out three concurrent jobs (analyze / optimize / convert) that race to set status. Poll until you see completed or failed; intermediate values (analyzing/optimizing/converting) indicate work is still in flight.

Success Response β€” 200 OK

{
  "data": {
    "job_id": "01hwz3p4kj0000000000000000",
    "status": "completed",
    "image": {
      "id": "01hwz3p4kj0000000000000000",
      "status": "completed",
      "original_filename": "photo.jpg",
      "original_size": 2048000,
      "optimized_size": 142336,
      "converted_format": "webp",
      "converted_size": 98304,
      "compression_percentage": 93,
      "translations": [
        {
          "language_code": "en",
          "seo_filename": "sustainable-leather-hiking-shoes",
          "seo_alt_text": "Sustainable hand-stitched leather shoes for urban hiking"
        },
        {
          "language_code": "de",
          "seo_filename": "nachhaltige-leder-wanderschuhe",
          "seo_alt_text": "Nachhaltige handgenΓ€hte Lederschuhe fΓΌr das Wandern in der Stadt"
        }
      ]
    }
  }
}

Error Responses

404 Not Found
{ "message": "No query results for model [App\\Models\\Image]." }

Code Samples

curl https://ultrapixx.com/api/v1/jobs/01hwz3p4kj0000000000000000 \
  -H "Authorization: Bearer $API_KEY"
// Poll until completed or failed
do {
    sleep(2);
    $response = Http::withToken($apiKey)
        ->get("https://ultrapixx.com/api/v1/jobs/" . $jobId);
    $status = $response->json("data.status");
} while (! in_array($status, ["completed", "failed"], true));

$image = $response->json("data.image");
GET /images/{id}/optimized API Key required

Download the TinyPNG-compressed binary of a completed optimization job. Returns the raw image file with the original MIME type. Ensure the job status is done before calling this endpoint.

Success Response β€” 200 OK

Headers
Content-Type: image/jpeg
Content-Disposition: attachment; filename="photo-optimized.jpg"

Response body is the binary image data.

Error Responses

404 β€” Optimization not ready
{ "error": "Optimized file not available. Ensure the optimization job has completed." }

Code Samples

curl -o optimized.jpg \
  -H "Authorization: Bearer $API_KEY" \
  https://ultrapixx.com/api/v1/images/01hwz3p4kj0000000000000000/optimized
$response = Http::withToken($apiKey)
    ->get("https://ultrapixx.com/api/v1/images/" . $imageId . "/optimized");

file_put_contents("optimized.jpg", $response->body());