Contents
CatalogBetaVersion v1

Collector API

Send storefront events and consent to Nucleo Catalog, and read the size widget.

The Collector is the public, browser-facing door of Nucleo Catalog. A storefront sends behavioural events in batches (page and product views, searches, cart changes, checkout and purchase), reports consent changes, checks that it is connected, and reads the size recommendation widget for a product page.

It is called from shoppers' browsers — normally by the hosted script nucleo.js and by the Shopify checkout Web Pixel — and can be called by any server for testing.

Authentication is a pair: the installation's public key (pk_ + 32 hex characters) plus an allowed origin (one of the domains registered on the installation). The key is public and grants no read access to your data; the domain list is what protects it.

Privacy by design: nothing is written without granted consent, a shopper's identity is only accepted as a reference signed by your store, and it is only linked when the shopper granted the personalisation purpose.

Authentication

  • publicKeyHeaderAPI key · header · X-Nucleo-Key

    The public key as a header — checked first. For servers and tools only: from a browser a custom header triggers a CORS preflight, which the Collector does not answer.

  • publicKeyQueryAPI key · query · key

    The installation's public key: pk_ followed by 32 lowercase hex characters. A missing or malformed key answers 404.

    It is read, in order, from the X-Nucleo-Key header, then from the key field of the JSON body (the browser transport for POST /events and POST /consent, since sendBeacon cannot set headers), then from the ?key= query parameter (the usual way for the GET operations).

    Get it in Settings › Catalog › Search › Installations (owner or admin role): each installation shows its public key, allowed domains and a ready-to-paste <script> snippet. Rotating the key disables the old one immediately. The key is public by design; the allowed domains are what protect it.

Base URL
https://api-catalog.nucleoplatform.com/api/collect/v1Production
Who calls it
Storefronts
Endpoints
4
OpenAPI 3.1 specification
collector.yaml

Events

Batches of storefront events. Each batch is validated event by event: an event with an unknown kind, a malformed uid or a timestamp out of range is rejected on its own and the rest of the batch is stored. Only batch-level problems (no visitor id, invalid consent state, more than 50 events, bad test code, unsupported version) fail the whole batch with a 422.

post/events

Send a batch of events

Sends up to 50 events for one visitor in a single batch (body ≤ 64 KB).

Transport. Browsers should send the body as text/plain (e.g. navigator.sendBeacon or fetch(..., {mode: "no-cors", credentials: "omit"})) with the key in the key body field: a text/plain POST without custom headers is a CORS simple request and needs no preflight. The Collector does not answer CORS preflights, so application/json or the X-Nucleo-Key header only work from servers and tools such as curl.

Origin. On POST only the Origin header counts (a Referer alone is refused). Origin: null (the sandboxed Shopify Web Pixel) is accepted only when the installation has the Web Pixel enabled, and then only checkout_start and purchase events pass (other kinds are rejected with reason origin) and the channel is recorded as web-pixel.

Consent. If visitor.consent is not granted (compared after trimming and lower-casing) nothing is written — not even the visitor — and the response is 202 with stored: 0 and reason: "consent". If it is denied or revoked and the visitor is already known, the erasure described in POST /consent is applied.

Validation per event.

  • kind must be one of the seven supported kinds (kind).
  • uid is optional; when present it must match ^[A-Za-z0-9_-]{8,40}$ (uid).
  • at is optional (defaults to now) and must be RFC 3339; it must fall between 7 days ago and 5 minutes from now (time). If the batch carries sentAt and the browser clock differs from ours by more than 30 seconds and at most 24 hours, every at is shifted by the difference before the window check (the original value is kept as payload._client_at, the shift is returned in skew).
  • An event that is not a JSON object is rejected (shape).
  • payload must be a flat object of scalars with at most 20 keys and strings ≤ 500 characters; otherwise the payload is dropped (the event is kept) and its index is listed in payloadDropped. Only the keys allowed for the kind are kept (see each event schema); others are silently dropped and the event index is also listed in payloadDropped. Keys starting with _ are reserved.
  • page_view.path and product_view.from are stored without fragment and query string (except q); under /account, /checkout, /checkouts, /orders and /customer only the first segment is kept.
  • query (search only) is truncated to 200 characters with whitespace collapsed. A query that looks like personal data — an email address, 8+ consecutive digits, or a phone-like digit sequence (9+ digits with separators, or 6+ digits starting with +) — is withheld: stored as null, flagged, and its index listed in withheld.
  • Control characters (C0 and DEL) are stripped from every string.

Idempotency. An event with a uid is written at most once: re-sending it (or repeating it in the same batch) counts it in duplicates. Always set a random uid so retries are safe.

Identity. customer is a reference signed by your store (see CustomerReference). It is verified, and the visitor is linked to the customer only if visitor.purposes contains personalisation; otherwise the events stay anonymous and identityWithheld is true. A plain customer id is never accepted.

Product references. ref is matched to your Catalog by variant id, then SKU, then product id, then handle. Events whose reference does not match any product are stored anyway and counted in unmapped.

Carts. When payload.cart is present, add_to_cart / remove_from_cart / checkout_start / purchase update the visitor's cart. A cart token that belongs to another visitor is not touched (the event is still stored) and counted in cartRefused.

Test mode. With a test code (6 characters [A-Z0-9], generated in Catalog › Shoppers › Test events) the batch runs the full validation and product matching but writes nothing; the result appears live in Test events and the response carries test: true. An expired or unknown code still keeps the batch in test mode (testKnown: false).

A database error never produces a 500: the batch comes back 202 with every event rejected with reason storage.

Rate limits. 120 requests per minute per client IP, plus an emergency cap of 20,000 requests per minute per public key. The limits are shared by all Collector operations and are checked before the key is looked up.

POST https://api-catalog.nucleoplatform.com/api/collect/v1/events
Authentication: key query parameter or X-Nucleo-Key header
Rate limit: 120 requests per 1m, per IP

Headers

  • Originstring

    Set by the browser. Its host must equal one of the installation's domains, or be a subdomain of a wildcard domain (*.acme.example matches shop.acme.example and eu.shop.acme.example, not acme.example). null is accepted only when the installation has the Web Pixel enabled. An origin that does not match answers 403.

    Example: https://shop.acme.example

Request bodytext/plain, application/json

A batch of events. Send it as text/plain from browsers (the body is still JSON) or as application/json from servers. Maximum 64 KB.

  • keystring

    The installation's public key.

    pattern ^pk_[0-9a-f]{32}$
    Example: pk_3f9a1c7e5b2d4f60a8c1e9b7d3f5a2c4
  • v1 | "1"

    Contract version. Optional; when present must be 1 (number or string).

    Example: 1
  • sentAtstring (date-time)

    Browser time when the batch was sent. Used to correct clock skew between 30 seconds and 24 hours. An unreadable value is ignored.

  • visitorVisitorrequired
    Child attributes
    • idstringrequired

      Opaque browser identifier generated by the storefront: Shopify's _shopify_y cookie value (so the theme and the checkout Web Pixel share the same visitor) or 32 random hex characters. Ids starting with demo (any case) are reserved and rejected.

      pattern ^[A-Za-z0-9_-]{16,64}$
      Example: 8b1f0c2e9d7a4b3c6e5f1a2b3c4d5e6f
    • consentstringrequired

      Case-insensitive; surrounding spaces are ignored.

      One ofgranteddeniedpendingrevoked
    • purposesarray of string

      Consent purposes. Only personalisation changes behaviour: without it events stay anonymous and the size widget stays impersonal. Items beyond the 10th are ignored; each item is trimmed to 32 characters. The storefront script maps Shopify's analyticsProcessingAllowed() to analytics and marketingAllowed() to personalisation.

      max items 10
    • consentSourcestring

      Where the consent decision came from. Any other value is ignored (stored as null).

      One ofshopifymanualgpc
    • localestring

      Default locale for the batch's events (truncated to 16 characters).

      max length 16
      Example: it
    • channelstring

      Default channel for the batch's events (truncated to 64 characters).

      max length 64
      Example: web
  • sessionstring

    Optional session id (same format as the visitor id). A malformed value is ignored.

    pattern ^[A-Za-z0-9_-]{16,64}$
    Example: s_4c2a9e1b7f3d5a60
  • customerstring

    A customer reference signed by your store, in the form v1.<storeId>.<shopifyCustomerId>.<expiresAt>.<signature> where expiresAt is a Unix timestamp (at most 24 hours ahead; 15 minutes is recommended) and signature is the lowercase hex HMAC-SHA256 of v1.<storeId>.<shopifyCustomerId>.<expiresAt> with the store's storefront secret. In a Shopify theme it is produced with Liquid's hmac_sha256 filter and exposed as <meta name="nucleo-customer" content="…">, which the script picks up. Wrong store, expired, malformed or badly signed references are treated as anonymous, never as errors.

    max length 200
    Example: v1.12.7012345678.1791104400.9c1e4b7a2f0d3c6e8b5a1f4d7c0e3b6a9d2f5c8e1b4a7d0c3f6e9b2a5d8c1f4e
  • teststring

    Test code from Catalog › Shoppers › Test events (valid for 60 minutes, one per store). Trimmed and upper-cased before validation. A present but malformed value fails the request with 422. The storefront script also picks it up from ?nucleo_test=<code> in any page URL.

    pattern ^[A-Z0-9]{6}$
    Example: K7Q2ZP
  • eventsarray of EventBase & object | EventBase & object | EventBase & object | EventBase & object | EventBase & object | EventBase & object | EventBase & object

    The events, in any order. An empty list is valid.

    max items 50default []

Responses

  • 202The batch was received. Inspect the counters to see what was stored: the storefront usually does not read the response (no-cors, sendBeacon), it is there for testing.
    Headers
    • Access-Control-Allow-Origin Echoes the request Origin when it was present and allowed.
    • Vary Always Origin.
    • X-RateLimit-Limit Requests allowed per minute for the client IP.
    • X-RateLimit-Remaining Requests left in the current minute.

    One of the following shapes:

    EventsResult
    • acceptedintegerrequired

      Events that passed validation.

    • storedintegerrequired

      Events actually written (always 0 in test mode).

    • duplicatesintegerrequired

      Events skipped because their uid was already stored or repeated in the batch.

    • rejectedarray of RejectedEventrequired
      Attributes of each item
      • indexintegerrequired

        Zero-based position of the event in the batch.

        Example: 4
      • reasonstringrequired

        shape not an object · kind unsupported kind · origin kind not allowed with Origin: null · uid malformed uid · time unreadable or out-of-window timestamp · storage the database refused the batch.

        One ofshapekindoriginuidtimestorage
    • payloadDroppedarray of integerrequired

      Indexes of events whose payload (or some of its keys) was dropped.

    • withheldarray of integerrequired

      Indexes of search events whose query was withheld as possible personal data.

    • skewintegerrequired

      Seconds added to every at to correct the browser clock (0 when not corrected).

    • unmappedintegerrequired

      Stored events whose ref matched no product in the Catalog.

    • cartRefusedintegerrequired

      Events whose cart token belongs to another visitor (event stored, cart untouched). Always 0 in test mode.

    • identifiedbooleanrequired

      The customer reference verified and the visitor was linked to the customer.

    • identityWithheldbooleanrequired

      A customer reference was sent but personalisation was not granted, so events stay anonymous.

    • visitorstringrequired

      The visitor id of the batch.

    • testtrue

      Present only in test mode.

    • testKnownboolean

      Present only in test mode — whether the code is the store's active test code.

    EventsNoConsentResult
    • acceptedintegerrequired
    • stored0required
    • reason"consent"required
    • rejectedarray of RejectedEventrequired
      Attributes of each item
      • indexintegerrequired

        Zero-based position of the event in the batch.

        Example: 4
      • reasonstringrequired

        shape not an object · kind unsupported kind · origin kind not allowed with Origin: null · uid malformed uid · time unreadable or out-of-window timestamp · storage the database refused the batch.

        One ofshapekindoriginuidtimestorage
    • visitorstringrequired
    • testtrue
    • testKnownboolean
    EventsStorageResult
    • acceptedintegerrequired
    • stored0required
    • rejectedarray of RejectedEventrequired
      Attributes of each item
      • indexintegerrequired

        Zero-based position of the event in the batch.

        Example: 4
      • reasonstringrequired

        shape not an object · kind unsupported kind · origin kind not allowed with Origin: null · uid malformed uid · time unreadable or out-of-window timestamp · storage the database refused the batch.

        One ofshapekindoriginuidtimestorage
    • visitorstringrequired
    • testtrue
    • testKnownboolean
  • 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.
    • messagestringrequired
  • 404The key is missing, malformed or unknown (no detail is given on purpose).
    • messagestringrequired
  • 409The store behind the key is not provisioned yet.
    • messagestringrequired
  • 413The body exceeds 64 KB.
    • messagestringrequired
  • 422The batch as a whole is not valid. Nothing is written. Note that errors maps each field to a single message string (not an array).
    Headers
    • Access-Control-Allow-Origin Echoes the request Origin when it was present and allowed.
    • messagestringrequired
    • errorsobjectrequired

      Field path → one message string.

  • 429Rate limit exceeded (120 requests per minute per IP, or 20,000 per minute per key). Nothing is written.
    Headers
    • Retry-After Seconds to wait before retrying.
    • X-RateLimit-Limit Requests allowed per minute for the client IP.
    • X-RateLimit-Remaining Always 0 on a 429.
    • X-RateLimit-Reset Unix timestamp at which the window resets.
    • messagestringrequired
Request
curl -X POST "https://api-catalog.nucleoplatform.com/api/collect/v1/events?key=$NUCLEO_KEY" \
  -H 'Origin: https://shop.acme.example' \
  -H 'Content-Type: text/plain' \
  -d '{
  "key": "pk_3f9a1c7e5b2d4f60a8c1e9b7d3f5a2c4",
  "v": 1,
  "sentAt": "2026-10-04T09:31:02.418Z",
  "visitor": {
    "id": "8b1f0c2e9d7a4b3c6e5f1a2b3c4d5e6f",
    "consent": "granted",
    "purposes": [
      "analytics",
      "personalisation"
    ],
    "consentSource": "shopify",
    "locale": "it",
    "channel": "web"
  },
  "session": "s_4c2a9e1b7f3d5a60",
  "customer": "v1.12.7012345678.1791104400.9c1e4b7a2f0d3c6e8b5a1f4d7c0e3b6a9d2f5c8e1b4a7d0c3f6e9b2a5d8c1f4e",
  "events": [
    {
      "uid": "e-7f3a9c1b20",
      "kind": "page_view",
      "at": "2026-10-04T09:30:12.004Z",
      "market": "IT",
      "payload": {
        "type": "collection",
        "path": "/collections/men",
        "collection": "men",
        "filters": "filter.v.option.color=Black;filter.v.price.lte=80",
        "sort": "price-ascending"
      }
    },
    {
      "uid": "e-7f3a9c1b21",
      "kind": "product_view",
      "at": "2026-10-04T09:30:40.551Z",
      "ref": {
        "product": "8123456789",
        "variant": "44001234567",
        "handle": "classic-tee-black",
        "sku": "TEE-BLK-M"
      },
      "payload": {
        "price": "29.00",
        "currency": "EUR",
        "pos": 3,
        "list": "collection:men",
        "from": "/collections/men"
      }
    },
    {
      "uid": "e-7f3a9c1b22",
      "kind": "search",
      "at": "2026-10-04T09:30:55.120Z",
      "query": "black hoodie",
      "payload": {
        "results": 12
      }
    },
    {
      "uid": "e-7f3a9c1b23",
      "kind": "add_to_cart",
      "at": "2026-10-04T09:31:01.870Z",
      "ref": {
        "variant": "44001234567",
        "sku": "TEE-BLK-M"
      },
      "payload": {
        "cart": "c1-9f2b7e4a1d",
        "quantity": 1,
        "price": "29.00",
        "currency": "EUR"
      }
    }
  ]
}'
Response
{
  "accepted": 4,
  "stored": 3,
  "duplicates": 1,
  "rejected": [
    {
      "index": 4,
      "reason": "kind"
    }
  ],
  "payloadDropped": [
    1
  ],
  "withheld": [],
  "skew": 0,
  "unmapped": 0,
  "cartRefused": 0,
  "identified": true,
  "identityWithheld": false,
  "visitor": "8b1f0c2e9d7a4b3c6e5f1a2b3c4d5e6f"
}

Installation

Connectivity check for the installation behind a public key.

get/config

Check the installation is connected

Returns the installation behind the key: the script uses it to know it is connected, and you can open it from the browser address bar while testing. For this GET the origin is taken from Origin, or from Referer when Origin is absent. A paused installation answers 403.

Rate limits. Shared with all Collector operations: 120 requests per minute per IP, 20,000 per minute per key.

GET https://api-catalog.nucleoplatform.com/api/collect/v1/config
Authentication: key query parameter or X-Nucleo-Key header
Rate limit: 120 requests per 1m, per IP

Headers

  • Originstring

    Set by the browser. Its host must equal one of the installation's domains, or be a subdomain of a wildcard domain (*.acme.example matches shop.acme.example and eu.shop.acme.example, not acme.example). null is accepted only when the installation has the Web Pixel enabled. An origin that does not match answers 403.

    Example: https://shop.acme.example
  • Refererstring

    On GET operations only, used for the origin check when Origin is absent.

    Example: https://shop.acme.example/products/classic-tee-black

Responses

  • 200The installation is active and the origin is allowed.
    Headers
    • Access-Control-Allow-Origin Echoes the request Origin when it was present and allowed.
    • Vary Always Origin.
    • oktruerequired
    • storestringrequired

      Store slug.

      Example: acme
    • installationstringrequired

      Installation name.

      Example: Acme EU storefront
    • statusstringrequired

      Always active (a paused installation answers 403).

      One ofactive
    • localesarray of stringrequired
    • pixelEnabledbooleanrequired

      Whether Origin: null (the checkout Web Pixel) is accepted.

  • 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.
    • messagestringrequired
  • 404The key is missing, malformed or unknown (no detail is given on purpose).
    • messagestringrequired
  • 409The store behind the key is not provisioned yet.
    • messagestringrequired
  • 429Rate limit exceeded (120 requests per minute per IP, or 20,000 per minute per key). Nothing is written.
    Headers
    • Retry-After Seconds to wait before retrying.
    • X-RateLimit-Limit Requests allowed per minute for the client IP.
    • X-RateLimit-Remaining Always 0 on a 429.
    • X-RateLimit-Reset Unix timestamp at which the window resets.
    • messagestringrequired
Request
curl -X GET "https://api-catalog.nucleoplatform.com/api/collect/v1/config?key=$NUCLEO_KEY" \
  -H 'Origin: https://shop.acme.example' \
  -H 'Referer: https://shop.acme.example/products/classic-tee-black' \
  -H 'Accept: application/json'
Response
{
  "ok": true,
  "store": "acme",
  "installation": "Acme EU storefront",
  "status": "active",
  "locales": [
    "it",
    "en"
  ],
  "pixelEnabled": true
}

Widgets

Read-only widgets for product pages, served with the same public key, origin check and consent rules as the events.

get/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:

  1. a customer reference signed by your store is supplied and verifies (a plain id is ignored);
  2. the visitor has granted consent including the personalisation purpose (recorded via POST /consent or an events batch);
  3. 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.

GET https://api-catalog.nucleoplatform.com/api/collect/v1/size/{product}
Authentication: key query parameter or X-Nucleo-Key header
Rate limit: 120 requests per 1m, per IP

Path parameters

  • productintegerrequired

    The Nucleo Catalog product id (numeric), not the Shopify product id.

    min 1
    Example: 4821

Query parameters

  • visitorstring

    The visitor id used in the events batches. Used only to read the visitor's consent.

    max length 64
    Example: 8b1f0c2e9d7a4b3c6e5f1a2b3c4d5e6f
  • customerstring

    The signed customer reference (see CustomerReference). Ignored when the X-Nucleo-Customer-Ref header is present.

    max length 512
    Example: v1.12.7012345678.1791104400.9c1e4b7a2f0d3c6e8b5a1f4d7c0e3b6a9d2f5c8e1b4a7d0c3f6e9b2a5d8c1f4e

Headers

  • X-Nucleo-Customer-Refstring

    The signed customer reference, for server-side callers. Takes precedence over customer (max 512 characters).

    max length 512
  • Originstring

    Set by the browser. Its host must equal one of the installation's domains, or be a subdomain of a wildcard domain (*.acme.example matches shop.acme.example and eu.shop.acme.example, not acme.example). null is accepted only when the installation has the Web Pixel enabled. An origin that does not match answers 403.

    Example: https://shop.acme.example
  • Refererstring

    On GET operations only, used for the origin check when Origin is absent.

    Example: https://shop.acme.example/products/classic-tee-black

Responses

  • 200Always answered, with or without a personal recommendation.
    Headers
    • Access-Control-Allow-Origin Echoes the request Origin when it was present and allowed.
    • Vary Always Origin.
    • dataobjectrequired
      Child attributes
      • productobjectrequired
        Child attributes
        • idinteger
        • sizesarray of string

          Sizes the product is sold in, in wearing order. Empty for one-size, unpublished or unknown products.

      • readingSizeReading | nullrequired
        SizeReading
        • directionstring
          One ofruns_largeruns_smallas_expected
        • basisstring

          product this item's own swaps; otherwise items of the same segment, fit (and type).

          One ofproductgender-fit-typegender-fit
        • peopleinteger

          Shoppers whose swaps back the reading (at least 8 for a product, 40 for a family).

        • sharenumber

          Share of swaps towards the larger size.

        • basenumber

          The same share for the whole segment, for comparison.

        • fitstring | null

          The product's fit attribute value.

        • segmentstring

          The product's gender segment (unknown when not set).

          Example: man
        • saysstring

          A ready-made English sentence.

      • adviceSizeAdvice | nullrequired
        SizeAdvice
        • sizestring
          Example: M
        • usualstring

          The shopper's usual size on this segment and scale.

          Example: L
        • stepinteger

          Steps from the usual size (never more than one).

          One of-101
        • segmentstring
          Example: man
        • scalestring

          Size scale identifier.

          Example: alpha
        • basisstring
          One ofproductgender-fit-typegender-fitnone
        • peopleinteger
        • sharenumber | null
        • basenumber | null
        • fitstring | null
        • confidentboolean

          Whether the usual size is settled (an unsettled size is never adjusted).

        • keptinteger

          Items kept in the usual size.

        • seeninteger

          Items considered.

        • reasonstring
          One ofalignedstepunsettledgapno-largerno-smallerno-fit-data
        • saysstring

          A ready-made English sentence (third person, for staff or UI copy).

      • personalisedbooleanrequired
      • whystring | nullrequired

        Why the answer is not personal: anonymous no customer reference · unverified the reference did not verify · no-consent the visitor has not granted personalisation · no-history not enough purchase history · no-sizes the product has no sizes (or is not published). null when 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.
    • messagestringrequired
  • 404The key is missing, malformed or unknown (no detail is given on purpose).
    • messagestringrequired
  • 409The store behind the key is not provisioned yet.
    • messagestringrequired
  • 422A query parameter is too long (standard validation error shape).
    • messagestringrequired
    • errorsobjectrequired
  • 429Rate limit exceeded (120 requests per minute per IP, or 20,000 per minute per key). Nothing is written.
    Headers
    • Retry-After Seconds to wait before retrying.
    • X-RateLimit-Limit Requests allowed per minute for the client IP.
    • X-RateLimit-Remaining Always 0 on a 429.
    • X-RateLimit-Reset Unix timestamp at which the window resets.
    • messagestringrequired
Request
curl -X GET "https://api-catalog.nucleoplatform.com/api/collect/v1/size/4821?key=$NUCLEO_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'
Response
{
  "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
  }
}