Calling a Try-On API From Python: A Worked Example
By the ZeDaq.ai team · · 4 min read
On this page
This worked example is for calling a try-on API from Python: base64-encode the shopper's photo and your product image, send them in a JSON POST to the ZeDaq.ai /api/v1/tryon endpoint with an x-api-key header, and poll if you get a 202. The requests library keeps this short.
This worked example assumes you have read the virtual try-on API overview. The same call in other languages is in calling a try-on API from PHP and from Node.js. The endpoint is also in the API reference.
What do you need before you start?
- A ZeDaq.ai API key from Dashboard → API keys.
- Python 3 and the
requestslibrary (pip install requests). - A full-length photo of a person and an image of the garment, as JPEG or PNG.
The docs say a full-length photo around 800px wide works well. Keep the key in an environment variable, as covered in using an x-api-key header safely.
What does the request look like?
You send a JSON body to POST https://www.zedaq.ai/api/v1/tryon.
| Field | Required | Meaning |
|---|---|---|
person_image_base64 |
Yes | The shopper's photo, base64 encoded |
product_image_base64 |
Yes | Your garment image, base64 encoded |
garment_type |
No | upper_body, lower_body or dresses |
A 200 response returns image_base64 and mime_type. A 202 response means the render is still running and gives a job_id and a poll_url.
How do you write the script?
import base64
import os
import time
import requests
BASE = "https://www.zedaq.ai"
HEADERS = {"x-api-key": os.environ["ZEDAQ_API_KEY"]}
def b64(path):
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode("ascii")
def try_on(person_path, product_path, garment_type="upper_body"):
body = {
"person_image_base64": b64(person_path),
"product_image_base64": b64(product_path),
"garment_type": garment_type,
}
r = requests.post(f"{BASE}/api/v1/tryon", json=body, headers=HEADERS, timeout=60)
data = r.json()
while r.status_code == 202:
time.sleep(2)
r = requests.get(BASE + data["poll_url"], headers=HEADERS, timeout=30)
data = r.json()
if r.status_code != 200:
raise RuntimeError(f'{data.get("error")}: {data.get("message")}')
return data
result = try_on("person.jpg", "shirt.png")
with open("result.png", "wb") as f:
f.write(base64.b64decode(result["image_base64"]))
Why poll every 2 seconds?
The API reference says to poll the poll_url every 2 seconds until it returns 200 with the image. Usage is only charged once a render succeeds.
How do you handle errors?
Errors return { "error": "code", "message": "..." }. The script above raises with both fields, so your logs show the cause. Add a retry limit to the loop so a stuck job cannot run forever.
How do you use it in a Flask route?
Keep the key on the server and let your page call your own route. A minimal Flask version looks like this:
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.post("/tryon")
def tryon_route():
person = request.files["person"].read()
product = request.files["product"].read()
# Encode both files, call the ZeDaq.ai API as shown above, return the image
return jsonify({"status": "ok"})
Fill in the middle with the same requests call. For a store without a custom backend, the WooCommerce route needs no code.
How do you test the script?
- Set the key in your shell:
export ZEDAQ_API_KEY=.... - Put a clear full-length photo named
person.jpgand a product image namedshirt.pngnext to the script. - Run
python tryon.pyand openresult.png. - Try a bad key on purpose and confirm that your error message shows the
errorcode. - Try a cropped photo and see how the result and the error handling behave.
How do you return the image from Flask?
Return the base64 string and MIME type as JSON, and let the page build a data: URL from them. This keeps your route simple and avoids storing result files on disk.
What about large batches?
If you render many products for one shopper, send the requests one after another and handle each 202 in turn. Keep the key on the server, and respect the monthly try-on cap on your plan.
What should you check before going live?
- The key is read from an environment variable.
- The loop has a retry limit.
- You show the shopper a loading state while a
202is pending. - You tested a person photo and a garment that differ from your examples.
Make your first try-on request from Python
FAQs
Which Python library should I use?
Any HTTP library works. The example uses requests because it is common and short.
Do I need to resize images first?
The docs say a full-length photo around 800px wide works well. Large files take longer to encode and send.
What does a 202 response mean?
The render is still running. Poll the poll_url until it returns 200 with the finished image.
Can I call this from the browser instead?
Keep the key on your server and call the API from there. Browser code exposes the key to anyone who views the source.
Try ZeDaq.ai free
Virtual try-on and Find my size for your store, plus client, order and invoicing tools for tailors, in one subscription.


