
Virtual Try-On API Integration: A Developer’s Guide to Endpoints, Batch Jobs and Webhooks
Integrating a virtual try-on API comes down to three calls: upload a photo of the person, upload a photo of the garment, then ask for a try-on that combines the two. Everything else — outfits, catalogue-scale jobs, webhooks, credit handling — is a variation on that pattern. This guide walks through a production-ready integration with the FashClick B2B API, in the order you will actually build it, and flags the decisions that tend to trip teams up.
Who this guide is for
The FashClick virtual try-on API is for teams who want try-on somewhere a no-code plugin cannot reach: a custom storefront, a marketplace with thousands of sellers, a mobile app, or an internal pipeline that produces on-model imagery for a catalogue. If you run a standard Shopify store and simply want a “Try it on” button, the Shopify app is quicker — see how to add try-on to Shopify. If you need control over where try-on appears and what happens to the results, read on.
The API is plain REST over HTTPS with JSON bodies. There is no client library to install; any language that can make an HTTP request — Node, Python, C#, PHP, Go — will do. The developer docs carry copy-ready examples in cURL, JavaScript, Python and C#.
The integration at a glance
Before writing code, it helps to see the moving parts. Every endpoint lives under /api/b2b/v1.
| Step | Endpoint | What you get back |
|---|---|---|
| Check your key | GET /me | Account name, plan and remaining credit balance |
| Upload the shopper or model | POST /person-images | A reusable personImageId |
| Upload the product | POST /garment-images | A reusable garmentImageId |
| One person, one garment | POST /tryon | A queued requestId |
| One person, up to 25 garments | POST /tryon/multi | A queued requestId, one image per garment |
| Many independent items | POST /tryon/batch | A batchId plus a request per item |
| Read status and images | GET /tryon/{requestId} and /results | Status, counts, credits charged, image URLs |
Generation is asynchronous. A try-on call returns 202 straight away with the request queued, and the finished image arrives later — either when you poll, or when FashClick calls your webhook. Design for that from day one and the rest of the integration falls into place.
Step 1 — Get a key and choose test or live
Sign up, open the API Keys page in the dashboard and create a test key. Keys look like fck_test_… or fck_live_…, and you send exactly one per request, either as an X-Api-Key header or as Authorization: Bearer fck_….
Test and live use the same endpoints but keep their request logs, credits and webhooks separate. Note that test mode still charges credits, from a separate test wallet, so it is a sandbox for your logs and webhooks rather than a free tier. Make your first call GET /me: if it returns your account name, plan and balance, authentication works.
Keep keys on the server. An API key in front-end JavaScript or a mobile app bundle can be read by anyone. Your browser or app should talk to your own backend, and only your backend should talk to FashClick.
Step 2 — Upload person and garment images
Person images
POST /person-images is a multipart upload of a JPG or PNG showing one clearly visible person. The response includes a personImageId you can reuse across as many try-ons as you like, so upload a shopper’s photo once per session rather than once per product.
Person images are deleted from FashClick storage automatically 30 days after upload. If you keep your own copy, your retention policy applies to that copy — our guide to handling shopper photos safely covers consent, retention and what to tell shoppers.
Garment images and categories
POST /garment-images works the same way but needs a category field, which tells the AI how to drape the item:
- UpperBody — shirts, tops, jackets.
- LowerBody — trousers, skirts, shorts.
- FullBody — dresses, jumpsuits, complete outfits.
- Accessories — bags, hats, jewellery.
The single most common integration mistake is mapping categories carelessly. Map them from your own product taxonomy in one place, and treat an unmapped product type as an error rather than a guess. Garment IDs are reusable, so a sensible pattern is to upload each product image once when it is created or updated in your catalogue and store the garmentImageId alongside the product.
Step 3 — Choose single, multi or batch
Single try-on
POST /tryon takes one personImageId and one garmentImageId and produces one image for 1 credit. It is the right call for a “Try it on” button on a product page. You can attach a free-form metadata string, such as an order or session reference, which comes back on the webhook so you can match results to your own records.
Multi try-on
POST /tryon/multi takes one person and up to 25 garments, and returns one image per garment. Use it when a shopper wants to compare several pieces, or when you want to show one model in every colourway of a product. It reserves one credit per garment up front, but only successful images are charged.
Batch try-on
POST /tryon/batch is for catalogue work: up to 100 independent items in one call, each with its own person and up to 25 garments. Every item becomes its own request, and all of them share a batchId. This is how you generate on-model imagery for a new season’s range overnight instead of one image at a time.
Check the balance before a big batch. If the wallet cannot cover the credits a batch reserves, the API rejects it with a400that states the exact shortfall. CallGET /mefirst, or listen for theCredits.Lowevent, so a scheduled job does not fail quietly at 2am.
Step 4 — Get results: polling vs webhooks
Each try-on response includes links to two read endpoints: GET /tryon/{requestId} for aggregate status, counts and credits charged, and GET /tryon/{requestId}/results for the per-garment results and image URLs. Batches add GET /tryon/batch/{batchId} for a roll-up of every child request.
Polling every few seconds is fine while you prototype. In production, use webhooks: they are faster, they cost you no wasted requests, and the TryOn.Completed payload already contains the full results array with image URLs, so there is no follow-up call to make.
Which events to subscribe to
- Per request:
TryOn.Completed,TryOn.PartiallyCompletedandTryOn.Failed. - Per batch:
Batch.Completed,Batch.PartiallyCompletedandBatch.Failedwhen the last item finishes. - Streaming:
TryOn.ResultReadyfires as each image in a multi or batch request lands, andBatch.Progressfires after each child request with batch-level counters — ideal for a live progress bar. - Account:
Credits.Low,Credits.ExhaustedandApiKey.Rotated.
For a shopper-facing button, TryOn.Completed is usually all you need. For a merchandising tool that shows 25 colourways, subscribe to TryOn.ResultReady so images appear one by one instead of all at once at the end.
Step 5 — Verify and handle webhooks properly
You create webhook endpoints in the Developer section of the dashboard. FashClick POSTs each event with three headers: X-FashClick-Event (the event type), X-FashClick-Timestamp (Unix seconds) and X-FashClick-Signature (a hex HMAC-SHA256 of the timestamp, a full stop and the raw body, keyed with your signing secret).
- Verify before you parse. Compute the HMAC over the raw body exactly as received — re-serialised JSON will not match — and compare it with a constant-time function.
- Respond quickly. Acknowledge with a
2xx, then do slow work such as downloading images or updating product pages in a background job. - Be idempotent. Failed deliveries are retried after 30 seconds, 2 minutes, 10 minutes, 1 hour and 6 hours, so the same event can reach you more than once. Key your processing on
requestIdand ignore events you have already handled. - Watch the dashboard. After the fifth failed attempt a delivery is abandoned and the endpoint is flagged, so alert on it rather than discovering it a week later.
Step 6 — Errors and credit reconciliation
The API uses standard status codes: 400 for validation problems (with a structured body that names the field), 401 for a missing or bad key, 403 for plan or permission issues and 429 when you are rate-limited. Retry 429s with backoff; do not retry 400s, which will fail the same way again.
Credits are simple: each successful image costs one credit and failed images are free. Every TryOn.* and Batch.* webhook carries creditsCharged and creditsRemaining, so your backend can keep a running ledger per customer, brand or campaign without an extra API call. Credits come from your plan or from one-off top-ups on the My Plan page.
A go-live checklist
- API key stored as a server-side secret, never in client code.
- One function that maps your product types to UpperBody, LowerBody, FullBody or Accessories.
- Garment images uploaded once per product version, with IDs stored next to the product.
- Webhook signatures verified on the raw body with a constant-time comparison.
- Webhook handling idempotent on
requestId, with slow work moved to a queue. - Partial results handled — show the images that succeeded and explain the rest.
- A
Credits.Lowalert wired to someone who can top up. - Your privacy notice updated to explain what happens to shoppers’ photos.
- Switched from a
fck_test_key to afck_live_key, with live webhooks configured separately.
The bottom line
A solid virtual try-on API integration is less about the try-on call and more about what surrounds it: reusable image IDs, the right garment category, asynchronous results delivered by signed webhooks, and credits you can reconcile. Get those right and the same few endpoints will power a product-page button, a merchandising tool or an overnight catalogue job. Explore the FashClick virtual try-on API, then grab a test key and work through the developer docs.
Frequently asked questions
How do I integrate a virtual try-on API into my store or app?
With FashClick you create an API key, upload a person photo and a garment photo to get two reusable IDs, then send those IDs to the try-on endpoint. The request is queued and you either poll its results endpoint or receive a signed webhook when the image is ready. All calls are plain HTTPS with JSON, so any backend language works.
How does the FashClick API authenticate requests?
Every request carries one API key, either in the X-Api-Key header or as Authorization: Bearer. Test keys start with fck_test_ and live keys with fck_live_. Keys belong on your server only and should never be shipped in browser or mobile app code.
What is the difference between single, multi and batch try-on?
Single try-on is one person and one garment, producing one image. Multi try-on is one person with up to 25 garments, producing one image per garment. Batch try-on submits up to 100 independent items in one call, each with up to 25 garments, all grouped under one batch ID.
How many credits does an API try-on use?
Each successful image uses one credit and failed images are free. Multi and batch requests reserve the full number of credits up front but only charge for the images that succeed. Every try-on and batch webhook reports creditsCharged and creditsRemaining.
How do I verify that a webhook came from FashClick?
Each delivery includes X-FashClick-Timestamp and X-FashClick-Signature headers. Compute a hex HMAC-SHA256 of the timestamp, a full stop and the raw request body using your signing secret, and compare it with the signature using a constant-time comparison before trusting the payload.
How long are shopper photos kept when using the API?
Person images uploaded through the API are automatically deleted from FashClick storage 30 days after upload. A personImageId can be reused for many try-ons within that window.


