REST API · Live

VTON API vs CALA — Virtual Try-On API for Fashion E-Commerce

Comparing VTON API vs CALA? PixelAPI's virtual try-on API lets developers dress any model in any garment with a single REST call — no sales call, no enterprise contract, no minimum commitment. Send a garment image and a person image, get a photorealistic composite back in under 30 seconds. $0.025 per try-on image — approximately 4× cheaper than FASHN AI, and a fraction of the cost of enterprise platforms like CALA, Zyler, or Veesual. 500 free credits, no credit card required.

$0.025 / image < 30s typical 500 free credits No credit card 3 garment categories Webhook support
Get an API key (free) Quick start See pricing API docs

Quick start — one API call

Sign up, copy your key from the dashboard, and POST two base64-encoded images (garment + person). The endpoint returns a job_id. Poll until status=completed, then download your composite from output_url or read it straight from result_image_b64.

# 1. Submit the try-on job
curl -X POST https://api.pixelapi.dev/v1/virtual-tryon \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "garment_image": "'$(base64 -w0 shirt.jpg)'",
    "person_image":  "'$(base64 -w0 model.jpg)'",
    "category": "upperbody"
  }'
# Response: {"job_id":"uuid","status":"queued","eta_seconds":30,...}

# 2. Poll for the result
curl https://api.pixelapi.dev/v1/virtual-tryon/jobs/JOB_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
# Response: {"status":"completed","output_url":"https://...","result_image_b64":"..."}
import base64, time, requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.pixelapi.dev"

def b64(path):
    with open(path, "rb") as f:
        return base64.b64encode(f.read()).decode()

# Submit
resp = requests.post(f"{BASE}/v1/virtual-tryon",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "garment_image": b64("shirt.jpg"),
        "person_image": b64("model.jpg"),
        "category": "upperbody",  # upperbody | lowerbody | dress
    }
)
job_id = resp.json()["job_id"]

# Poll until done
while True:
    r = requests.get(f"{BASE}/v1/virtual-tryon/jobs/{job_id}",
        headers={"Authorization": f"Bearer {API_KEY}"}).json()
    if r["status"] == "completed":
        print("Done:", r["output_url"])
        break
    time.sleep(5)
import fs from "fs";
import fetch from "node-fetch";

const API_KEY = process.env.PIXELAPI_KEY;
const BASE = "https://api.pixelapi.dev";

const b64 = (path) => fs.readFileSync(path).toString("base64");

// Submit
const job = await fetch(`${BASE}/v1/virtual-tryon`, {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    garment_image: b64("shirt.jpg"),
    person_image: b64("model.jpg"),
    category: "upperbody",
  }),
}).then(r => r.json());

// Poll
let result;
do {
  await new Promise(r => setTimeout(r, 5000));
  result = await fetch(`${BASE}/v1/virtual-tryon/jobs/${job.job_id}`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  }).then(r => r.json());
} while (result.status !== "completed");

console.log("Done:", result.output_url);
<?php
$API_KEY = getenv("PIXELAPI_KEY");
$BASE    = "https://api.pixelapi.dev";

function b64($path) { return base64_encode(file_get_contents($path)); }

// Submit
$ch = curl_init("$BASE/v1/virtual-tryon");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ["Authorization: Bearer $API_KEY", "Content-Type: application/json"],
    CURLOPT_POSTFIELDS     => json_encode([
        "garment_image" => b64("shirt.jpg"),
        "person_image"  => b64("model.jpg"),
        "category"      => "upperbody",
    ]),
]);
$job = json_decode(curl_exec($ch), true);
$job_id = $job["job_id"];

// Poll
do {
    sleep(5);
    $ch2 = curl_init("$BASE/v1/virtual-tryon/jobs/$job_id");
    curl_setopt_array($ch2, [CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ["Authorization: Bearer $API_KEY"]]);
    $result = json_decode(curl_exec($ch2), true);
} while ($result["status"] !== "completed");

echo $result["output_url"];
require "net/http"
require "json"
require "base64"

API_KEY = ENV["PIXELAPI_KEY"]
BASE    = URI("https://api.pixelapi.dev")

def b64(path) = Base64.strict_encode64(File.binread(path))

# Submit
http = Net::HTTP.new(BASE.host, 443)
http.use_ssl = true
req = Net::HTTP::Post.new("/v1/virtual-tryon",
  "Authorization" => "Bearer #{API_KEY}", "Content-Type" => "application/json")
req.body = {garment_image: b64("shirt.jpg"), person_image: b64("model.jpg"),
             category: "upperbody"}.to_json
job = JSON.parse(http.request(req).body)

# Poll
loop do
  sleep 5
  r = JSON.parse(http.request(
    Net::HTTP::Get.new("/v1/virtual-tryon/jobs/#{job['job_id']}",
      "Authorization" => "Bearer #{API_KEY}")
  ).body)
  break puts r["output_url"] if r["status"] == "completed"
end
package main

import (
    "bytes"; "encoding/base64"; "encoding/json"; "fmt"
    "io"; "net/http"; "os"; "time"
)

const apiKey = "YOUR_API_KEY"
const base = "https://api.pixelapi.dev"

func b64File(path string) string {
    data, _ := os.ReadFile(path)
    return base64.StdEncoding.EncodeToString(data)
}

func main() {
    body, _ := json.Marshal(map[string]any{
        "garment_image": b64File("shirt.jpg"),
        "person_image":  b64File("model.jpg"),
        "category":      "upperbody",
    })
    req, _ := http.NewRequest("POST", base+"/v1/virtual-tryon", bytes.NewReader(body))
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")
    resp, _ := http.DefaultClient.Do(req)
    var job map[string]any
    json.NewDecoder(resp.Body).Decode(&job)

    for {
        time.Sleep(5 * time.Second)
        r, _ := http.NewRequest("GET", base+"/v1/virtual-tryon/jobs/"+job["job_id"].(string), nil)
        r.Header.Set("Authorization", "Bearer "+apiKey)
        out, _ := http.DefaultClient.Do(r)
        var result map[string]any
        json.NewDecoder(out.Body).Decode(&result)
        if result["status"] == "completed" {
            fmt.Println(result["output_url"])
            break
        }
        io.Copy(io.Discard, out.Body)
    }
}

VTON API vs CALA — pricing comparison

CALA and most enterprise virtual try-on platforms require a sales engagement and do not publish per-image pricing. PixelAPI's virtual try-on API is self-serve with transparent, per-image billing — no annual commitment, no minimum spend.

ProviderFree tierPer try-on priceSelf-serve APIGarment categories
PixelAPI 500 credits, no card $0.025 ✓ Yes upperbody · lowerbody · dress
FASHN AI 10 complimentary credits $0.10 (1 credit/image min.) ✓ Yes see fashn.ai/pricing
CALA No Contact sales Enterprise only see ca.la/pricing
Zyler No Contact sales Enterprise only see zyler.com/pricing
Veesual No Contact sales Enterprise only see veesual.ai/pricing
Outfit.ai No Contact sales Enterprise only see outfit.ai/pricing

FASHN AI pricing verified from fashn.ai/pricing, May 2026. CALA, Zyler, Veesual, and Outfit.ai do not publish per-image API pricing — contact each vendor for a quote. PixelAPI's per-image price is set at approximately half the cheapest publicly available rival rate.

What you get back

Composite image via URL

When the job is complete, output_url returns a temporary signed URL to the generated JPEG or PNG composite. Pipe it straight to your CDN, Shopify storefront, or product database. No intermediate file handling required.

Base64 result for server pipelines

If your server-side pipeline needs immediate bytes, result_image_b64 in the job response contains the full image as a base64 string — decode it and write to disk, a database, or an S3 bucket in a single step.

Multiple samples per call

Set n_samples=2, 3, or 4 to get multiple output variants from a single garment + person pair. Useful for A/B testing product photos or showing multiple color-ways side-by-side.

Webhook delivery

Pass webhook_url in your request and PixelAPI will POST the completed result to your endpoint — no polling loop needed. Ideal for serverless functions, Zapier webhooks, or background job processors.

API parameters at a glance

ParameterTypeDefaultDescription
garment_imagestring (base64)requiredClothing item to try on — JPEG, PNG, or WebP, max 10 MB
person_imagestring (base64)requiredModel or person photo — JPEG, PNG, or WebP, max 10 MB
categorystringupperbodyupperbody · lowerbody · dress
n_samplesinteger1Number of output images (1–4). Each costs 25 credits.
n_stepsinteger40Refinement steps (1–50). Higher = more detail, slower.
image_scalefloat2.0Prompt-following strength (0.1–10.0)
webhook_urlstringnullPOST result to this HTTPS URL when complete

Common workflows for fashion e-commerce

The Virtual Try-On API slots into these production workflows. Each links to a use-case setup guide:

Fashion catalog generation

Pair virtual try-on with AI image generation to spin up catalog shots from product photos alone — no studio, no model booking.

Fashion ad creatives

Auto-generate on-model product imagery for paid social and display ads without per-SKU photo shoots.

Garment cutout pipeline

Remove garment backgrounds before feeding them into the try-on API for cleaner composites.

E-commerce product editing

Combine virtual try-on with AI image editing to relight, recolor, and retouch the finished composite in one pipeline.

High-res product upscaling

Upscale try-on outputs to print-quality resolution for lookbooks, billboards, and marketplace listings.

Visual search integration

Index try-on output images in a visual search engine so shoppers can find similar garments by photo.

Integrations

PixelAPI works with any HTTP client and the platforms your team already uses.

Shopify

Trigger virtual try-on on product upload via Shopify webhooks. Attach composite images to product metafields automatically.

Zapier

Connect virtual try-on to any app in your stack with a no-code Zapier workflow — no backend required.

Make.com

Drag-and-drop virtual try-on into Make scenarios. Route job results to Google Drive, Airtable, Notion, or Slack.

Webflow

Auto-populate Webflow CMS product entries with on-model try-on imagery via the Webflow API + PixelAPI webhook.

Comparison vs alternatives

VTON API vs Veesual

Veesual requires a 4-week enterprise onboarding. PixelAPI is self-serve in minutes at $0.025/image with a free trial.

vs Replicate

Replicate charges per-second compute; PixelAPI charges per finished image with a predictable flat rate and auto-refund on failed jobs.

All API alternatives

Browse the full comparison index for background removal, upscaling, image editing, and more.

Rate limits & error handling

The virtual try-on endpoint allows 10 requests per minute on all tiers. If you exceed the limit, the API returns HTTP 429 with a Retry-After header. Use exponential backoff starting at 5 seconds — the Python and Node SDKs handle this automatically. For bulk batch pipelines, email [email protected] to discuss higher concurrency limits.

If a job fails (bad input, NSFW rejection, or a processing error), credits are automatically refunded. You never pay for a broken result. The error_message field on the job status response describes the failure reason.

# Python — simple polling with backoff
import time, requests

def poll_vton(job_id, api_key, timeout=120):
    deadline = time.time() + timeout
    delay = 5
    while time.time() < deadline:
        r = requests.get(
            f"https://api.pixelapi.dev/v1/virtual-tryon/jobs/{job_id}",
            headers={"Authorization": f"Bearer {api_key}"}
        ).json()
        if r["status"] == "completed":
            return r["output_url"]
        if r["status"] == "failed":
            raise RuntimeError(r.get("error_message", "Job failed"))
        time.sleep(delay)
        delay = min(delay * 2, 30)  # cap at 30s
    raise TimeoutError("Job did not complete in time")

Frequently asked questions

What is CALA and how does it compare to PixelAPI's VTON API?

CALA (ca.la) is an enterprise fashion design and supply chain platform that includes virtual styling features as part of a broader managed service. It does not offer a self-serve API with transparent per-image pricing — engagement requires a sales conversation and custom contract. PixelAPI's virtual try-on API is a developer-first REST endpoint: sign up, copy your key, and make your first call in under five minutes. Pricing is $0.025 per try-on image with 500 free credits and no credit card required.

What does the PixelAPI virtual try-on API cost?

$0.025 per output image (25 credits at $0.001/credit). New accounts get 500 free credits — enough for 20 try-on images — with no credit card required. FASHN AI charges $0.10 per image on their self-serve plan; PixelAPI is approximately 4× cheaper. CALA, Zyler, Veesual, and Outfit.ai all require enterprise agreements with non-public pricing.

What garment categories does the virtual try-on API support?

The API supports three clothing categories: upperbody (shirts, jackets, blazers, tops), lowerbody (trousers, skirts, shorts, jeans), and dress (full-length garments). Pass the category parameter in your JSON request body. The default is upperbody.

What image formats does the VTON API accept?

Both the garment image and the person/model image must be base64-encoded JPEG, PNG, or WebP — up to 10 MB each. Pass them as base64 strings in the JSON body. Data URL prefixes (data:image/jpeg;base64,...) are automatically stripped if present.

How do I call the virtual try-on API?

POST a JSON body with garment_image and person_image (both base64-encoded) to https://api.pixelapi.dev/v1/virtual-tryon with your Bearer API key. You'll receive a job_id. Poll GET /v1/virtual-tryon/jobs/{job_id} until status=completed, then download the result from output_url or read it from result_image_b64. See the Quick Start section above for ready-to-run code in 6 languages.

How long does a virtual try-on take?

A single try-on (n_samples=1) typically completes in under 30 seconds. The response includes an eta_seconds field as a guide. Capacity is kept warm 24/7 — your first request is as fast as your thousandth.

Can I generate multiple try-on images in one API call?

Yes. Set n_samples to 2, 3, or 4. Each additional sample costs another 25 credits ($0.025). Four samples typically finish in under two minutes. Each output image is returned separately via output_url and result_image_b64.

What does the API return when the job is complete?

The job status response includes output_url (a temporary signed URL to the composite image) and result_image_b64 (the same image as a base64 string). Use output_url for browser/CDN delivery and result_image_b64 for server-side pipelines that need immediate bytes.

Is there a free trial?

Yes. Every new account starts with 500 free credits — enough for 20 virtual try-on images — with no credit card required. You can upgrade to a paid plan when you need more. Paid plans start at $10 for 10,000 credits ($0.001/credit).

What are the rate limits for the virtual try-on API?

The default limit is 10 requests per minute on all tiers. Exceeding it returns HTTP 429 with a Retry-After header. Use exponential backoff starting at 5 seconds. For bulk batch pipelines, email [email protected] with your expected volume to discuss higher limits.

Can I receive results via webhook instead of polling?

Yes. Pass webhook_url in your JSON request body and PixelAPI will POST the completed job result to your endpoint the moment processing finishes. This eliminates the polling loop for server-to-server integrations and serverless functions.

Does the VTON API work with any model photo?

Yes, as long as the model photo is a clear front-facing image with the person fully visible at sufficient resolution. The API accepts any JPEG, PNG, or WebP up to 10 MB. All inputs are screened by an automated safety layer before processing — images that fail the check are rejected and credits are not charged.

Start free — 500 credits, no card Read full API docs Compare all plans