API Documentation

Integrate our service into your applications with a simple REST API.

Quick Start

Remove a background in three steps. Choose your language:

1

Get your API key

Sign up and subscribe to a paid plan to get your API key from the dashboard. Use it as a Bearer token in all requests:

Header
Authorization: Bearer YOUR_API_TOKEN
2

Upload an image for background removal

curl -X POST https://www.print-ready.ai/api/images/remove-background \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "image=@photo.jpg" \
  -F "quality=basic"

# Returns 202 with image ID and status "pending"
import requests

response = requests.post(
    "https://www.print-ready.ai/api/images/remove-background",
    headers={"Authorization": f"Bearer {token}"},
    files={"image": open("photo.jpg", "rb")},
    data={"quality": "basic"}
)
image_id = response.json()["data"]["id"]
const form = new FormData();
form.append("image", fileInput.files[0]);
form.append("quality", "basic");

const response = await fetch("https://www.print-ready.ai/api/images/remove-background", {
  method: "POST",
  headers: { "Authorization": `Bearer ${token}` },
  body: form
});
const imageId = (await response.json()).data.id;
$response = Http::withToken($token)
    ->attach('image', file_get_contents('photo.jpg'), 'photo.jpg')
    ->post('https://www.print-ready.ai/api/images/remove-background', [
        'quality' => 'basic',
    ]);
$imageId = $response->json('data.id');
3

Poll until complete, then download

# Poll for completion
while true; do
  STATUS=$(curl -s https://www.print-ready.ai/api/images/$IMAGE_ID \
    -H "Authorization: Bearer YOUR_API_TOKEN" \
    | jq -r '.data.status')
  echo "Status: $STATUS"
  [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ] && break
  sleep 3
done

# Download the result
curl -s https://www.print-ready.ai/api/images/$IMAGE_ID/download \
  -H "Authorization: Bearer YOUR_API_TOKEN"
import time

# Poll for completion
while True:
    result = requests.get(
        f"https://www.print-ready.ai/api/images/{image_id}",
        headers={"Authorization": f"Bearer {token}"}
    ).json()
    status = result["data"]["status"]
    print(f"Status: {status}")
    if status in ("completed", "failed"):
        break
    time.sleep(3)

# Get the download URL
download = requests.get(
    f"https://www.print-ready.ai/api/images/{image_id}/download",
    headers={"Authorization": f"Bearer {token}"}
).json()
print(download["data"]["url"])
// Poll for completion
let result;
while (true) {
  const res = await fetch(`https://www.print-ready.ai/api/images/${imageId}`, {
    headers: { "Authorization": `Bearer ${token}` }
  });
  result = await res.json();
  console.log(`Status: ${result.data.status}`);
  if (["completed", "failed"].includes(result.data.status)) break;
  await new Promise(r => setTimeout(r, 3000));
}

// Get the download URL
const dl = await fetch(`https://www.print-ready.ai/api/images/${imageId}/download`, {
  headers: { "Authorization": `Bearer ${token}` }
});
const { data } = await dl.json();
console.log(data.url);
// Poll for completion
do {
    $result = Http::withToken($token)
        ->get("https://www.print-ready.ai/api/images/{$imageId}")
        ->json();
    $status = $result['data']['status'];
    echo "Status: {$status}\n";
    if (in_array($status, ['completed', 'failed'])) break;
    sleep(3);
} while (true);

// Get the download URL
$download = Http::withToken($token)
    ->get("https://www.print-ready.ai/api/images/{$imageId}/download")
    ->json();
echo $download['data']['url'];

Overview

The Print-Ready API lets you integrate AI-powered image processing into your applications. Remove backgrounds, edit images with AI instructions, and upscale to print-ready resolution -- all via simple REST endpoints. Processing is asynchronous: submit an image, poll for completion, then download the result.

Base URL

https://www.print-ready.ai/api

Authentication

Bearer token via Sanctum

Format

Multipart upload, JSON response

Available Endpoints

Method Endpoint Description Credits
POST /api/images/remove-background Remove image background 1-2
POST /api/images/edit AI-powered image editing 1
POST /api/images/upscale Upscale image resolution 1
GET /api/images List processed images 0
GET /api/images/{id} Get image details & status 0
GET /api/images/{id}/download Get temporary download URL 0
DELETE /api/images/{id} Delete an image 0
POST /api/batches Create a batch job varies
GET /api/batches List batches 0
GET /api/batches/{id} Get batch status 0
DELETE /api/batches/{id} Cancel & delete batch 0
GET /api/user Get account info 0
GET /api/usage Get usage stats & remaining credits 0
GET /api/subscription Get subscription details 0
GET /api/user/tokens List API tokens 0
DELETE /api/user/tokens/{id} Revoke a specific API token 0
POST /api/auth/logout Revoke current token 0

Supported Image Formats

All image processing endpoints accept the following file types via multipart form upload:

JPEG PNG WebP BMP TIFF GIF

Maximum file size: 10 MB per image.

Authentication

All API requests must include a Bearer token in the Authorization header. Generate your API key from the dashboard.

Authorization Header
Authorization: Bearer YOUR_API_TOKEN

API access requires a paid plan. Free-tier accounts can only use the web interface. Upgrade to Starter or higher to unlock API access.

You can also include Accept: application/json to ensure error responses are returned as JSON rather than HTML.

Account & Usage

Retrieve your account info, credit usage, subscription details, and manage API tokens. These endpoints do not consume credits.

GET /api/user

Get the authenticated user's profile and current plan.

Response (200 OK)
{
  "success": true,
  "message": "User retrieved successfully",
  "data": {
    "id": 3,
    "name": "Jane Doe",
    "email": "jane@example.com",
    "email_verified_at": "2026-03-11T18:22:26.000000Z",
    "profile_photo_url": "https://...",
    "created_at": "2026-03-11T13:59:45.000000Z",
    "updated_at": "2026-03-11T23:47:20.000000Z",
    "pricing_plan": {
      "id": 3,
      "name": "Pro",
      "slug": "professional"
    }
  }
}
GET /api/usage

Get your current credit usage, remaining balance, and plan features.

Response (200 OK)
{
  "success": true,
  "message": "Usage statistics retrieved successfully",
  "data": {
    "plan": { "name": "Pro", "slug": "professional" },
    "usage": {
      "used": 14,
      "limit": 300,
      "remaining": 286,
      "unlimited": false,
      "exceeded": false,
      "percentage": 4.67
    },
    "features": {
      "api_access": true,
      "batch_processing": true
    }
  }
}
GET /api/subscription

Get your Stripe subscription status, plan details, and feature limits.

Response (200 OK)
{
  "success": true,
  "message": "Subscription details retrieved successfully",
  "data": {
    "subscription": {
      "id": 1,
      "type": "default",
      "status": "active",
      "quantity": 1,
      "trial_ends_at": null,
      "ends_at": null,
      "is_active": true,
      "is_on_trial": false,
      "is_cancelled": false,
      "is_on_grace_period": false
    },
    "plan": {
      "name": "Pro",
      "slug": "professional",
      "price": 3900,
      "features": { "api_access": true, "batch_processing": true },
      "limits": { "credits_per_month": 300, "max_batch_size": 20 }
    }
  }
}
GET /api/user/tokens

List all API tokens for your account, including abilities and last usage.

Response (200 OK)
{
  "success": true,
  "message": "API tokens retrieved successfully",
  "data": {
    "tokens": [
      {
        "id": 1,
        "name": "api-key",
        "abilities": ["read", "write", "delete", "user:read"],
        "last_used_at": "2026-03-12T22:59:31.000000Z",
        "created_at": "2026-03-11T18:22:26.000000Z"
      }
    ],
    "count": 1
  }
}
DELETE /api/user/tokens/{id}

Revoke a specific API token by ID. The token will immediately stop working.

POST /api/auth/logout

Revoke the token used to make this request. Useful for implementing logout in client applications.

Remove Background

Remove the background from an image. Choose between basic (1 credit) and plus quality (2 credits) for higher fidelity edge detection.

POST /api/images/remove-background
Parameters (multipart/form-data)
image *
file

The image file to process. JPEG, PNG, WebP, BMP, TIFF, or GIF. Max 10 MB.

quality
string, optional

Processing quality level. Default: basic

basic -- Standard removal, 1 credit

plus -- Higher fidelity edges, 2 credits

curl -X POST https://www.print-ready.ai/api/images/remove-background \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "image=@product-photo.jpg" \
  -F "quality=plus"
response = requests.post(
    "https://www.print-ready.ai/api/images/remove-background",
    headers={"Authorization": f"Bearer {token}"},
    files={"image": open("product-photo.jpg", "rb")},
    data={"quality": "plus"}
)
print(response.json())
const form = new FormData();
form.append("image", fileInput.files[0]);
form.append("quality", "plus");

const response = await fetch("https://www.print-ready.ai/api/images/remove-background", {
  method: "POST",
  headers: { "Authorization": `Bearer ${token}` },
  body: form
});
console.log(await response.json());
$response = Http::withToken($token)
    ->attach('image', file_get_contents('product-photo.jpg'), 'product-photo.jpg')
    ->post('https://www.print-ready.ai/api/images/remove-background', [
        'quality' => 'plus',
    ]);
dump($response->json());
Response (202 Accepted)
{
  "success": true,
  "message": "Background removal started. Your image is being processed.",
  "data": {
    "id": 42,
    "batch_id": null,
    "service": "bg_removal",
    "service_variant": "plus",
    "status": "pending",
    "credits_charged": 2,
    "original_filename": "product-photo.jpg",
    "original_size": 1048576,
    "original_dimensions": { "width": 1920, "height": 1080 },
    "processing_params": null,
    "created_at": "2026-03-08T12:00:00.000000Z",
    "updated_at": "2026-03-08T12:00:00.000000Z"
  }
}

Edit Image

Apply AI-powered edits to an image using natural language instructions. Costs 1 credit per image.

POST /api/images/edit
Parameters (multipart/form-data)
image *
file

The image file to edit. JPEG, PNG, WebP, BMP, TIFF, or GIF. Max 10 MB.

instructions *
string

Natural language editing instructions. 3-1000 characters. Be specific for best results.

Example: "Make the sky more vibrant and add warm sunset tones"

curl -X POST https://www.print-ready.ai/api/images/edit \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "image=@landscape.png" \
  -F "instructions=Make the sky more vibrant and add warm sunset tones"
response = requests.post(
    "https://www.print-ready.ai/api/images/edit",
    headers={"Authorization": f"Bearer {token}"},
    files={"image": open("landscape.png", "rb")},
    data={"instructions": "Make the sky more vibrant and add warm sunset tones"}
)
print(response.json())
const form = new FormData();
form.append("image", fileInput.files[0]);
form.append("instructions", "Make the sky more vibrant and add warm sunset tones");

const response = await fetch("https://www.print-ready.ai/api/images/edit", {
  method: "POST",
  headers: { "Authorization": `Bearer ${token}` },
  body: form
});
console.log(await response.json());
$response = Http::withToken($token)
    ->attach('image', file_get_contents('landscape.png'), 'landscape.png')
    ->post('https://www.print-ready.ai/api/images/edit', [
        'instructions' => 'Make the sky more vibrant and add warm sunset tones',
    ]);
dump($response->json());
Response (202 Accepted)
{
  "success": true,
  "message": "Image editing started. Your image is being processed.",
  "data": {
    "id": 43,
    "batch_id": null,
    "service": "image_edit",
    "service_variant": null,
    "status": "pending",
    "credits_charged": 1,
    "original_filename": "landscape.png",
    "original_size": 2097152,
    "original_dimensions": { "width": 3840, "height": 2160 },
    "processing_params": {
      "instructions": "Make the sky more vibrant and add warm sunset tones"
    },
    "created_at": "2026-03-08T12:01:00.000000Z",
    "updated_at": "2026-03-08T12:01:00.000000Z"
  }
}

Upscale Image

Upscale an image to a higher resolution using AI. Costs 1 credit per image. Choose 2x, 3x, or 4x scale factor.

POST /api/images/upscale
Parameters (multipart/form-data)
image *
file

The image file to upscale. JPEG, PNG, WebP, BMP, TIFF, or GIF. Max 10 MB.

scale_factor
integer, optional

Upscale multiplier. Default: 4

Accepted values: 2, 3, 4

curl -X POST https://www.print-ready.ai/api/images/upscale \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "image=@low-res.jpg" \
  -F "scale_factor=4"
response = requests.post(
    "https://www.print-ready.ai/api/images/upscale",
    headers={"Authorization": f"Bearer {token}"},
    files={"image": open("low-res.jpg", "rb")},
    data={"scale_factor": 4}
)
print(response.json())
const form = new FormData();
form.append("image", fileInput.files[0]);
form.append("scale_factor", "4");

const response = await fetch("https://www.print-ready.ai/api/images/upscale", {
  method: "POST",
  headers: { "Authorization": `Bearer ${token}` },
  body: form
});
console.log(await response.json());
$response = Http::withToken($token)
    ->attach('image', file_get_contents('low-res.jpg'), 'low-res.jpg')
    ->post('https://www.print-ready.ai/api/images/upscale', [
        'scale_factor' => 4,
    ]);
dump($response->json());
Response (202 Accepted)
{
  "success": true,
  "message": "Image upscaling started. Your image is being processed.",
  "data": {
    "id": 44,
    "batch_id": null,
    "service": "upscale",
    "service_variant": null,
    "status": "pending",
    "credits_charged": 1,
    "original_filename": "low-res.jpg",
    "original_size": 524288,
    "original_dimensions": { "width": 640, "height": 480 },
    "processing_params": {
      "scale_factor": 4
    },
    "created_at": "2026-03-08T12:02:00.000000Z",
    "updated_at": "2026-03-08T12:02:00.000000Z"
  }
}

Manage Images

List, retrieve, download, and delete your processed images. These endpoints do not consume credits.

GET /api/images

List all your processed images, ordered by most recent first. Supports pagination and filtering.

Query Parameters
per_page
integer, optional

Results per page (1-100). Default: 20

status
string, optional

Filter by status: pending, processing, completed, failed

service
string, optional

Filter by service type: bg_removal, image_edit, upscale

curl https://www.print-ready.ai/api/images?status=completed&per_page=10 \
  -H "Authorization: Bearer YOUR_API_TOKEN"
response = requests.get(
    "https://www.print-ready.ai/api/images",
    headers={"Authorization": f"Bearer {token}"},
    params={"status": "completed", "per_page": 10}
)
print(response.json())
const response = await fetch(
  "https://www.print-ready.ai/api/images?status=completed&per_page=10",
  { headers: { "Authorization": `Bearer ${token}` } }
);
console.log(await response.json());
$response = Http::withToken($token)
    ->get('https://www.print-ready.ai/api/images', [
        'status' => 'completed',
        'per_page' => 10,
    ]);
dump($response->json());
GET /api/images/{id}

Get details and processing status of a specific image. Use this to poll for completion after submitting a processing request.

Response (200 OK) -- Completed
{
  "success": true,
  "message": "Image retrieved successfully",
  "data": {
    "id": 42,
    "batch_id": null,
    "service": "bg_removal",
    "service_variant": "plus",
    "status": "completed",
    "credits_charged": 2,
    "original_filename": "product-photo.jpg",
    "original_size": 1048576,
    "original_dimensions": { "width": 1920, "height": 1080 },
    "processed_dimensions": { "width": 1920, "height": 1080 },
    "processed_size": 892416,
    "processing_time": 4.2,
    "processing_params": null,
    "download_url": "https://...",
    "created_at": "2026-03-08T12:00:00.000000Z",
    "updated_at": "2026-03-08T12:00:05.000000Z"
  }
}
GET /api/images/{id}/download

Get a temporary download URL for a completed image. The URL expires after 30 minutes. Returns 409 Conflict if the image is not yet completed.

Response (200 OK)
{
  "success": true,
  "message": "Download URL generated successfully",
  "data": {
    "url": "https://storage.example.com/processed/abc123.png?signature=...",
    "expires_at": "2026-03-08T12:30:00.000000Z",
    "filename": "product-photo.jpg"
  }
}
DELETE /api/images/{id}

Permanently delete a processed image and its entire session. If the image belongs to a batch, the entire batch and all sibling images are deleted. This action cannot be undone.

curl -X DELETE https://www.print-ready.ai/api/images/42 \
  -H "Authorization: Bearer YOUR_API_TOKEN"
response = requests.delete(
    f"https://www.print-ready.ai/api/images/{image_id}",
    headers={"Authorization": f"Bearer {token}"}
)
print(response.status_code)  # 200
const response = await fetch(`https://www.print-ready.ai/api/images/${imageId}`, {
  method: "DELETE",
  headers: { "Authorization": `Bearer ${token}` }
});
console.log(response.status);  // 200
$response = Http::withToken($token)
    ->delete("https://www.print-ready.ai/api/images/{$imageId}");
echo $response->status();  // 200

Batch Processing

Process up to 20 images in a single request. Each image in the batch is processed independently and you can track overall progress. Credit cost is per-image based on the service chosen.

Pro plan and above only. Batch processing is not available on Free or Starter plans. Max batch size varies by plan: Pro (20), Enterprise 1K (50), Enterprise 3K (100).

POST /api/batches

Create a batch with multiple images for processing. All images in the batch use the same service and settings. Returns a batch ID for tracking progress.

Parameters (multipart/form-data)
images[] *
file array

Array of image files. 1-20 images per batch. Each file max 10 MB. JPEG, PNG, WebP, BMP, TIFF, or GIF.

service *
string

Processing service to apply. One of: remove-background, edit, upscale

quality
string, conditional

Required when service is remove-background. Values: basic or plus

instructions
string, conditional

Required when service is edit. 3-1000 characters. Applied to all images in the batch.

scale_factor
integer, optional

For upscale service. Values: 2, 3, 4. Default: 4

name
string, optional

A name for the batch. Max 255 characters. Auto-generated if omitted.

curl -X POST https://www.print-ready.ai/api/batches \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "service=remove-background" \
  -F "quality=basic" \
  -F "name=Product photos batch" \
  -F "images[]=@photo1.jpg" \
  -F "images[]=@photo2.jpg" \
  -F "images[]=@photo3.jpg"
files = [
    ("images[]", open("photo1.jpg", "rb")),
    ("images[]", open("photo2.jpg", "rb")),
    ("images[]", open("photo3.jpg", "rb")),
]
response = requests.post(
    "https://www.print-ready.ai/api/batches",
    headers={"Authorization": f"Bearer {token}"},
    files=files,
    data={
        "service": "remove-background",
        "quality": "basic",
        "name": "Product photos batch"
    }
)
batch_id = response.json()["data"]["id"]
const form = new FormData();
form.append("service", "remove-background");
form.append("quality", "basic");
form.append("name", "Product photos batch");

// Add multiple files
for (const file of fileInput.files) {
  form.append("images[]", file);
}

const response = await fetch("https://www.print-ready.ai/api/batches", {
  method: "POST",
  headers: { "Authorization": `Bearer ${token}` },
  body: form
});
const batchId = (await response.json()).data.id;
$response = Http::withToken($token)
    ->attach('images[]', file_get_contents('photo1.jpg'), 'photo1.jpg')
    ->attach('images[]', file_get_contents('photo2.jpg'), 'photo2.jpg')
    ->attach('images[]', file_get_contents('photo3.jpg'), 'photo3.jpg')
    ->post('https://www.print-ready.ai/api/batches', [
        'service' => 'remove-background',
        'quality' => 'basic',
        'name' => 'Product photos batch',
    ]);
$batchId = $response->json('data.id');
Response (202 Accepted)
{
  "success": true,
  "message": "Batch created successfully. 3 images are being processed.",
  "data": {
    "id": 7,
    "name": "Product photos batch",
    "service": "bg_removal",
    "service_variant": "basic",
    "status": "pending",
    "total_images": 3,
    "completed_images": 0,
    "failed_images": 0,
    "credits_charged": 3,
    "images": [ ... ],
    "created_at": "2026-03-08T12:05:00.000000Z",
    "completed_at": null
  }
}
GET /api/batches

List all your batches, ordered by most recent first. Supports pagination via per_page query parameter (1-100, default 20).

GET /api/batches/{id}

Get batch details including progress counters and the status of each individual image in the batch.

Response (200 OK) -- In Progress
{
  "success": true,
  "message": "Batch retrieved successfully",
  "data": {
    "id": 7,
    "name": "Product photos batch",
    "service": "bg_removal",
    "service_variant": "basic",
    "status": "processing",
    "total_images": 3,
    "completed_images": 2,
    "failed_images": 0,
    "credits_charged": 3,
    "images": [
      {
        "id": 45,
        "service": "bg_removal",
        "status": "completed",
        "original_filename": "photo1.jpg",
        "download_url": "https://...",
        ...
      },
      ...
    ],
    "created_at": "2026-03-08T12:05:00.000000Z",
    "completed_at": null
  }
}
DELETE /api/batches/{id}

Cancel and delete a batch. Any pending or in-progress images will be cancelled. All associated files are permanently removed.

Credits

Each image processing operation consumes credits from your monthly allowance. Credits reset at the start of each billing cycle.

Operation Variant Credits
Background Removalbasic1 credit
Background Removalplus2 credits
AI Image Editing--1 credit
Image Upscaling--1 credit

Credit Response Headers

Every API response includes headers showing your current credit usage:

Response Headers
X-Credits-Limit: 300
X-Credits-Remaining: 247
X-Credits-Used: 53
Header Description
X-Credits-LimitTotal monthly credit allowance for your plan
X-Credits-RemainingCredits remaining in the current billing period
X-Credits-UsedCredits consumed in the current billing period

When you run out of credits, processing endpoints return 402 Payment Required. Upgrade your plan or wait for credits to reset at the next billing cycle.

Rate Limits

API requests are rate-limited per minute based on your subscription plan. Rate limits apply to all endpoints collectively.

Plan API Access Rate Limit Monthly Credits Batch Processing
Free No -- 3 (web only) --
Starter Yes 30 req/min 50 credits --
Pro Yes 120 req/min 300 credits Up to 20 images
Enterprise 1K Yes 300 req/min 1,000 credits Up to 50 images
Enterprise 3K Yes 300 req/min 3,000 credits Up to 100 images

Standard rate limit headers are included in all responses:

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 107
Retry-After: 60  (only on 429 responses)

Errors

The API uses standard HTTP status codes. Errors return a consistent JSON structure:

{
  "success": false,
  "message": "Human-readable error description",
  "errors": {
    "field": ["Validation error detail"]
  }
}
Code Meaning
401Missing or invalid API token
402Insufficient credits for the requested operation
403Feature not available on your plan, or you do not own this resource
404Image or batch not found
409Image not ready for download (still processing)
422Validation failed (missing required fields, invalid file type, etc.)
429Rate limit exceeded -- check Retry-After header
500Server error -- please retry or contact support