Shop the look
/v2/agent/matchFinds the products in a photo of someone dressed. The shop-the-look
models read the photo once, find every item the person wears
(garments, shoes, bags, jewellery, eyewear, hats), and match each one
against your store's products. For every item you get the best
product and the other high-scoring ones, best first, and whether the
top one is the exact product (match: exact) or the closest your
store sells (similar).
Experimental. Shop the look is new. Its request and response fields may change, and its matches are still improving.
A run takes about a second. No language model is involved: the models are trained for this and run on our servers.
The photo
Send it inline as a data: URI (PNG, JPEG or WebP, at most 8,000,000
characters), or as imageUrl, a public http(s) URL we fetch (a domain
name, not an IP address; redirects are not followed). Photos of a
person wearing the outfit work best; about 1024px on the long side is
plenty.
Which store
One store is searched. With itemId, the photo is that product's own
(a product page's model shot): its store is searched, the product is
read with its title, and it is never answered for itself — nor are
its other colourways, or the other pieces of a set it belongs to. This
is how the complete-the-look strip reads a product page. Without
itemId, datasetIds (default: every active dataset) is searched,
narrowed to one storefront by store.
A store's products are searchable once they are indexed, which
happens after each sync; indexed: false means none is yet.
Prices
Send country and every card is priced in that shopper's market. A
product the market does not sell gives way to the next alternate that
it does.
Request body
application/jsonrequiredThe photo as a data: URI — data:image/png;base64,…,
data:image/jpeg;base64,… or data:image/webp;base64,…. Longer
than 8,000,000 characters is refused with 413.
Or a public http(s) URL of the photo, fetched by us: a domain name,
never an IP address or an internal host, with no redirects, at most
12 MB. Used when image is absent.
The product the photo belongs to, when it is a product's own photo.
Its store is searched, it is read with its title, and it, its
colourways and its set's pieces are never offered. A 404 when it
is not a product in the resolved datasets.
Search these datasets. Omit or send [] to use every active
dataset in the organization. Ignored for scope when itemId is
sent (the product's store is searched), but still checked.
A storefront URL or domain, narrowing the datasets to that store's.
A 404 when no dataset in scope is that store.
The shopper's country, ISO 3166-1 alpha-2 in any case (US, ca);
on a Shopify storefront, Shopify.country. Cards are priced in
that shopper's market, and a product the market does not sell is
replaced by its next alternate that it does. Omitted, or for a
country the store does not sell into, cards carry the store's
default market's prices, flagged marketExact: false.
How many products to return per item besides the top one.
Response
Response headers
X-RateLimit-ResourceThe quota resource this endpoint is metered against: api.v2.agent.chat
for the chat endpoint, api.v2.agent.looks for the looks endpoint and
api.v2.agent.match for the shop-the-look endpoint. These are separate
from the v1 resources, so Agent API usage never draws down a v1
allowance.
X-RateLimit-Quota-LimitRequests allowed in the current billing period, or unlimited.
X-RateLimit-Quota-RemainingRequests left in the current billing period, or unlimited.
X-RateLimit-Quota-ResetUnix epoch seconds at which the billing period resets.
X-RateLimit-RPM-LimitRequests allowed per minute for this resource.
X-RateLimit-RPM-RemainingRequests left in the current one-minute window.
X-RateLimit-RPM-ResetUnix epoch seconds at which the one-minute window resets.
The items found, in the order the model is most sure of them. Empty when nothing the store sells is in the photo.
What it is, in a shopper's word — the top product's family (jacket, sneaker, tote bag), or the family read from the photo when the product has none.
What the model read in the photo, as slot/family in the product taxonomy.
The colour the model read, one of the taxonomy's colour families.
Where the item is in the photo, [x0, y0, x1, y1] as fractions of its width and height.
exact — the model is sure item is the product in the photo (on
stores it never trained on, 98.6% of its exact calls are right).
similar — item is the closest the store sells: a look-alike, or
the exact product when the model is not sure enough to say so.
exactsimilarA catalogue item as the match endpoint presents it — enough to draw a
card and link out, without the full Product record.
The next highest-scoring products, best first, one per product (colourways of one product are not repeated). As many as alternates asked for, or fewer.
false when none of the store's products is indexed yet (a store connected minutes ago); try again after its first sync has been processed.
Errors
32Every error is JSON with a single error string unless noted. Match on the status code; the message is for humans.
Request body must be valid JSON.The body could not be parsed as JSON.
Request body must be a JSON object.The body is empty, or is valid JSON that is not an object (for example an array).
No active datasets found for this organization. Activate one via the dashboard (Dataset → Settings) or through the REST API before proceeding.datasetIds was omitted and the organization has datasets, but none is active.
All requested datasets are archived. Reactivate at least one via the dashboard or REST API.Every dataset in datasetIds is archived.
No datasets found for this organization. Create one via the dashboard or REST API, or pass datasetIds to use draft/archived datasets before proceeding.The organization has no datasets at all.
itemId is not a product in these datasets.itemId is not a product of this organization in the resolved datasets.
store matches none of these datasets.store is not the storefront (storeDomain) of any dataset in scope.
image is too large.image is longer than 8,000,000 characters, or the photo at imageUrl is over 12 MB.
Send the photo as image (a data URL) or imageUrl.Neither image nor imageUrl was sent.
image must be a base64 data URL (png, jpeg or webp).image is not a string starting with data:image/png;base64,, data:image/jpeg;base64, (or jpg) or data:image/webp;base64,.
imageUrl: <reason>imageUrl is not an http(s) URL on a public domain name (an IP address, localhost or an internal name is refused).
imageUrl could not be fetched.The photo at imageUrl could not be fetched (a network error, a timeout, a redirect, or an error status, which is quoted), or is not an image.
alternates must be an integer from 0 to 4.alternates is present and not an integer from 0 to 4.
datasetIds must be an array of strings.datasetIds is present and is not an array, or contains a value that is not a string.
Invalid datasetIds for this organization: <ids>One or more of datasetIds does not belong to the organization. The offending ids are listed, comma-separated.
curl -X POST "https://stylor.ai/api/v2/agent/match" \
-H "Authorization: Bearer $STYLOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...",
"store": "shop.example.com",
"country": "US"
}'{
"indexed": true,
"garments": [
{
"slot": "jacket",
"family": "outerwear/jacket",
"colour": "black",
"box": [
0.18,
0.21,
0.83,
0.58
],
"match": "exact",
"item": {
"id": "8f2c1a9e-4b7d",
"itemId": "8f2c1a9e-4b7d-4c1e-9a3f-2d6b7e5c1a90",
"name": "Moto Leather Jacket",
"brand": "Acme",
"price": 340,
"currency": "USD",
"url": "https://shop.example.com/products/moto-leather-jacket",
"image": "https://stylor.ai/api/v1/image/org_5f3a/ds_9c21/8f2c1a9e-4b7d/0.jpg/-/resize/600x/-/format/jpeg",
"slot": "outerwear",
"family": "jacket",
"colour": "black"
},
"alternates": [
{
"id": "1b7e33c0-9a2d",
"itemId": "1b7e33c0-9a2d-4f8e-b5c6-7d8e9f0a1b2c",
"name": "Biker Jacket",
"brand": "Acme",
"price": 290,
"currency": "USD",
"url": "https://shop.example.com/products/biker-jacket",
"image": "https://stylor.ai/api/v1/image/org_5f3a/ds_9c21/1b7e33c0-9a2d/0.jpg/-/resize/600x/-/format/jpeg",
"slot": "outerwear",
"family": "jacket",
"colour": "black"
}
]
}
]
}