Contents
Widgets
Read-only widgets for product pages, served with the same public key, origin check and consent rules as the events.
Base URL, authentication and conventions of this API are on the Collector API page.
/size/{product}Get size advice for a product
Powers a size selector on the product page: the sizes the product is sold in, how it fits (from size swaps observed across shoppers, the same for everyone) and, when every condition below holds, the size recommended to the shopper who is looking.
The personal advice appears only if:
- a
customerreference signed by your store is supplied and verifies (a plain id is ignored); - the
visitorhas granted consent including thepersonalisationpurpose (recorded viaPOST /consentor an events batch); - the customer has enough purchase history.
Otherwise the answer stays impersonal and why says which condition was missing. A failed verification
is never an error. The response never contains the customer's size profile or purchase list, and the
call is not logged against the customer.
Only published products answer with sizes: a draft, archived or status-less product (or an unknown id)
answers like a product without sizes (why: "no-sizes"), so the widget can hide itself.
Same key and origin rules as the other operations (for this GET, Referer is accepted when Origin is
absent). From a browser, pass key, visitor and customer as query parameters: custom headers trigger
a CORS preflight that the Collector does not answer. The customer reference is short-lived (15 minutes by
default), so it is harmless in access logs.
Rate limits. Shared with all Collector operations: 120 requests per minute per IP, 20,000 per minute per key.
key query parameter or X-Nucleo-Key headerPath parameters
productintegerrequiredThe Nucleo Catalog product id (numeric), not the Shopify product id.
min 1Example:4821
Query parameters
visitorstringThe visitor id used in the events batches. Used only to read the visitor's consent.
max length 64Example:8b1f0c2e9d7a4b3c6e5f1a2b3c4d5e6fcustomerstringThe signed customer reference (see
CustomerReference). Ignored when theX-Nucleo-Customer-Refheader is present.max length 512Example:v1.12.7012345678.1791104400.9c1e4b7a2f0d3c6e8b5a1f4d7c0e3b6a9d2f5c8e1b4a7d0c3f6e9b2a5d8c1f4e
Headers
X-Nucleo-Customer-RefstringThe signed customer reference, for server-side callers. Takes precedence over
customer(max 512 characters).max length 512OriginstringrequiredRequired. Browsers set it; servers and tools must send it (on GET,
Refereris accepted instead). Its host must equal one of the installation's domains, or be a subdomain of a wildcard domain (*.acme.examplematchesshop.acme.exampleandeu.shop.acme.example, notacme.example). A wildcard must sit under your own registrable domain: it is refused on a public suffix (*.com,*.co.uk) and on shared platforms where every subdomain belongs to someone else (for example*.myshopify.com,*.vercel.app,*.netlify.app,*.github.io); such a wildcard saved earlier matches nothing. Register those hosts by their exact name.nullis accepted only when the installation has the Web Pixel enabled. An origin that does not match answers403.Example:https://shop.acme.exampleRefererstringOn GET operations only, used for the origin check when
Originis absent.Example:https://shop.acme.example/products/classic-tee-black
Responses
200Always answered, with or without a personal recommendation.application/json
HeadersAccess-Control-Allow-OriginEchoes the requestOriginwhen it was present and allowed.VaryAlwaysOrigin.
dataobjectrequiredChild attributes
productobjectrequiredChild attributes
idintegersizesarray of stringSizes the product is sold in, in wearing order. Empty for one-size, unpublished or unknown products.
readingSizeReading | nullrequiredSizeReading
directionstringOne ofruns_largeruns_smallas_expectedbasisstringproductthis item's own swaps; otherwise items of the same segment, fit (and type).One ofproductgender-fit-typegender-fitpeopleintegerShoppers whose swaps back the reading (at least 8 for a product, 40 for a family).
sharenumberShare of swaps towards the larger size.
basenumberThe same share for the whole segment, for comparison.
fitstring | nullThe product's fit attribute value.
segmentstringThe product's gender segment (
unknownwhen not set).Example:mansaysstringA ready-made English sentence.
adviceSizeAdvice | nullrequiredSizeAdvice
sizestringExample:MusualstringThe shopper's usual size on this segment and scale.
Example:LstepintegerSteps from the usual size (never more than one).
One of-101segmentstringExample:manscalestringSize scale identifier.
Example:alphabasisstringOne ofproductgender-fit-typegender-fitnonepeopleintegersharenumber | nullbasenumber | nullfitstring | nullconfidentbooleanWhether the usual size is settled (an unsettled size is never adjusted).
keptintegerItems kept in the usual size.
seenintegerItems considered.
reasonstringOne ofalignedstepunsettledgapno-largerno-smallerno-fit-datasaysstringA ready-made English sentence (third person, for staff or UI copy).
personalisedbooleanrequiredwhystring | nullrequiredWhy the answer is not personal:
anonymousno customer reference ·unverifiedthe reference did not verify ·no-consentthe visitor has not grantedpersonalisation·no-historynot enough purchase history ·no-sizesthe product has no sizes (or is not published).nullwhen personalised.One ofanonymousunverifiedno-consentno-historyno-sizesnull
403The installation is paused, or the origin is not one of its domains. Both answer the same body; the exact reason is visible to the merchant in Catalog › Shoppers › Test events. application/json
messagestringrequired
404The key is missing, malformed or unknown (no detail is given on purpose).application/json
messagestringrequired
409The store behind the key is not provisioned yet.application/json
messagestringrequired
422A query parameter is too long (standard validation error shape).application/json
messagestringrequirederrorsobjectrequired
429Rate limit exceeded (120 requests per minute per IP, or 20,000 per minute per key). Nothing is written. application/json
HeadersRetry-AfterSeconds to wait before retrying.X-RateLimit-LimitRequests allowed per minute for the client IP.X-RateLimit-RemainingAlways0on a 429.X-RateLimit-ResetUnix timestamp at which the window resets.
messagestringrequired
curl -X GET "https://api-catalog.nucleoplatform.com/api/collect/v1/size/4821?key=$NUCLEO_COLLECTOR_KEY&visitor=8b1f0c2e9d7a4b3c6e5f1a2b3c4d5e6f&customer=v1.12.7012345678.1791104400.9c1e4b7a2f0d3c6e8b5a1f4d7c0e3b6a9d2f5c8e1b4a7d0c3f6e9b2a5d8c1f4e" \
-H 'Origin: https://shop.acme.example' \
-H 'Referer: https://shop.acme.example/products/classic-tee-black' \
-H 'Accept: application/json'const res = await fetch(`https://api-catalog.nucleoplatform.com/api/collect/v1/size/4821?key=${process.env.NUCLEO_COLLECTOR_KEY}&visitor=8b1f0c2e9d7a4b3c6e5f1a2b3c4d5e6f&customer=v1.12.7012345678.1791104400.9c1e4b7a2f0d3c6e8b5a1f4d7c0e3b6a9d2f5c8e1b4a7d0c3f6e9b2a5d8c1f4e`, {
method: "GET",
headers: {
Origin: "https://shop.acme.example",
Referer: "https://shop.acme.example/products/classic-tee-black",
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-catalog.nucleoplatform.com/api/collect/v1/size/4821?key=' . getenv('NUCLEO_COLLECTOR_KEY') . '&visitor=8b1f0c2e9d7a4b3c6e5f1a2b3c4d5e6f&customer=v1.12.7012345678.1791104400.9c1e4b7a2f0d3c6e8b5a1f4d7c0e3b6a9d2f5c8e1b4a7d0c3f6e9b2a5d8c1f4e', [
'headers' => [
'Origin' => 'https://shop.acme.example',
'Referer' => 'https://shop.acme.example/products/classic-tee-black',
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"data": {
"product": {
"id": 4821,
"sizes": [
"XS",
"S",
"M",
"L",
"XL"
]
},
"reading": {
"direction": "runs_large",
"basis": "product",
"people": 64,
"share": 0.297,
"base": 0.512,
"fit": "oversize",
"segment": "man",
"says": "Runs large: 70% of the 64 shoppers who swapped size on this item kept the smaller one. Most people do better one size down from their usual."
},
"advice": {
"size": "M",
"usual": "L",
"step": -1,
"segment": "man",
"scale": "alpha",
"basis": "product",
"people": 64,
"share": 0.297,
"base": 0.512,
"fit": "oversize",
"confident": true,
"kept": 6,
"seen": 7,
"reason": "step",
"says": "Take M instead of their usual L: 70% of the 64 shoppers who swapped size on this item kept the smaller one."
},
"personalised": true,
"why": null
}
}{
"data": {
"product": {
"id": 4821,
"sizes": [
"XS",
"S",
"M",
"L",
"XL"
]
},
"reading": {
"direction": "as_expected",
"basis": "gender-fit",
"people": 412,
"share": 0.508,
"base": 0.512,
"fit": "regular",
"segment": "woman",
"says": "Fits as expected: the 412 shoppers who swapped size on 37 items that fit the same way split the same way as the rest of the range. Take your usual size."
},
"advice": null,
"personalised": false,
"why": "anonymous"
}
}{
"data": {
"product": {
"id": 4821,
"sizes": []
},
"reading": null,
"advice": null,
"personalised": false,
"why": "no-sizes"
}
}{
"message": "Forbidden."
}{
"message": "Not found."
}{
"message": "Store is not ready."
}{
"message": "The visitor field must not be greater than 64 characters.",
"errors": {
"visitor": [
"The visitor field must not be greater than 64 characters."
]
}
}{
"message": "Too Many Attempts."
}