Server-side recommendations
Use this when your server needs the shopper’s size: a headless storefront, server-rendered product pages, a size shown in a cart email, or your own recommendation logic.
How it works
Section titled “How it works”-
In the browser, TryYourSize.js asks our origin for a recommendation handle for the signed-in shopper.
const tys = TryYourSize("pk_live_…");const h = await tys.recommendationHandle(); // { handle, expiresAt } | nullnullmeans the shopper is not signed in to TryYourSize on this site, has no body yet, or is in your A/B holdout.expiresAtis an ISO date-time one hour ahead. In React, call it on the client fromuseTryYourSize(). -
Your page sends
h.handleto your own server, like any other value (a form field, a fetch to your API). -
Your server calls
POST /v1/recommendationswith a secret key (or a restricted key withfit_checks:read) and up to 25 products. -
The answer is one entry per product, in the order asked: sizes in your labels, never measurements.
import TryYourSize from "@tryyoursize/node";const tys = new TryYourSize(process.env.TYS_SECRET_KEY!);
const { mode, data } = await tys.recommendations.create({ handle: req.body.tysHandle, products: ["CREW-TSHIRT", "STRAIGHT-JEANS"],});for (const r of data) { if (r.status === "ready") console.log(r.product, r.size); // "CREW-TSHIRT", "Medium"}import tryyoursizetys = tryyoursize.TryYourSize(os.environ["TYS_SECRET_KEY"])
res = tys.recommendations.create( handle=request.form["tys_handle"], products=["CREW-TSHIRT", "STRAIGHT-JEANS"],)for r in res["data"]: if r["status"] == "ready": print(r["product"], r["size"])curl https://api.tryyoursize.com/v1/recommendations \ -H "Authorization: Bearer $TYS_SECRET_KEY" \ -H "TYS-Version: 2026-10-25" \ -H "Content-Type: application/json" \ -d '{"handle":"tys_rh_…","products":["CREW-TSHIRT","STRAIGHT-JEANS"]}'The answer
Section titled “The answer”{ "mode": "live", "data": [ { "product": "CREW-TSHIRT", "status": "ready", "size": "Medium", "studio_size": "M", "wearable_sizes": ["Medium", "Large"] }, { "product": "STRAIGHT-JEANS", "status": "unavailable", "size": null, "studio_size": null, "wearable_sizes": [] } ]}| Field | |
|---|---|
status |
ready (a size), computing (a simulation the shopper started is running: ask again later), none (simulated, no size is wearable), unavailable (no published garment, not simulated on this body yet, or the plan has no fit checks left). There is no signed_out: a handle always belongs to a signed-in shopper. |
size |
The recommended size in your label (the product’s size map), or null. |
studio_size |
The same size as entered in Studio, or null. |
wearable_sizes |
Sizes wearable on this body, in your labels. |
method |
A coarse, informational label of how the size was obtained. Do not build logic on its values. |
tryon_id |
The try-on that produced the size, when there is one. Send it back with orders for attribution. |
- It never starts a simulation. Like a page view, it answers only with a size that is already available (many garments answer in under a second); otherwise the status is
unavailableuntil the shopper asks for the try-on in our window. - A delivered size counts as a fit check, exactly as in the browser (once per shopper and product per 30 days, live mode only).
- Raw measurements are never accepted or returned by the server API.
The handle
Section titled “The handle”- It starts with
tys_rh_and is up to 4 KB. Treat it as opaque. - It is encrypted and sealed to one store, one mode and one shopper. Neither your page nor your server can read anything from it; it never carries the shopper’s email.
- It expires after 1 hour. After that the API answers
401with codehandle_expired: ask the browser for a new one. - It is refused with
401handle_invalidafter the shopper deletes their account or disconnects your store, and when it was issued for another store. - Its mode must match your key: a test handle with a live key (or the reverse) is
403handle_mode_mismatch.
Was this page helpful?
Thank you. We read every answer.