Fit Analytics Recommendation API Guide

This document serves as a guide for developers using the Fit Analytics Recommendation API. Here's the reference documentation of individual API endpoints: API reference documentation

1. Introduction

The Fit Analytics Recommendation API allows users to programmatically create and manage user profiles, access information needed to provide and configure an interface for a user to provide their information and ultimately provide a size or product recommendation based on the user's input.

The API is mostly built around the JSON-API specification. It only supports one type of response format, which are determined by the content of the Accept header:

  1. the plain JSON mode (Accept: application/json), which is basically a simplified and flattened equivalent of the JSON-API mode (see below), with included objects directly in-place

All API endpoints are secured by a token-based authentication requirement. The token is used in the Authorization header of all requests to endpoints that require authorization.

2. Get Started

Set up an authentication mechanism with asymmetric tokens

First thing we need to set up is an authentication process for the client to call the Fit Analytics back-end API.

So, initially, create an asymmetric set of keys and make the public keys available for us to configure in our back-end. We expect a JWKS (JSON Web Key Sets) in a plain file. If it is served via a public URL, it might look like: https://example.com/.well-known/jwks

The private generated key will then be used to sign the token (JWT) so then the client can make requests to the Fit Analytics back-end. The public keys (JWKS) will then be used to verify the token.

In addition to JWKS, our backend will validate the JWT against validation options that you can customize. They should be JSON like the following:

{
  algorithms: ["RS256"],
  issuer: "https://example.com/",
  audience: "https://widget.fitanalytics.com/api"
  subject: "XXXX",
  maxAge: "360 days",
  clockTolerance: 600,
}

For a full list of the options/requirements can be found here, and the full documentation of the library that we use to validate the JWT here.

IMPORTANT

Inform the Fit Analytics team about the JWKS file and the verification options used so that they're added to the back-end configuration.

JWT signature

The token signature encodes the visitor authentication information and it can be safely stored and used.

As the Fit Analytics back-end is only using asymmetric tokens, the token is generated directly on the client's backend using the private key and the customer-specific info (User ID and session ID). It should contain all information that is needed to authenticate the customer. The API validates the token signature against the public JWKS that has been previously registered with Fit Analytics.

When signing the key, the payload information should include:

  1. sub - subject; User ID (Only if it is a logged in user)
  2. sess - Session ID

And, the signing options should at least contain:

  1. kid - the Key Id


Example

A jsonwebtoken library example in Javascript.

const jwt = require("jsonwebtoken");

const pemString = "-----BEGIN RSA PRIVATE KEY-----\n ... "

const payload = {
  sub: "1000", // User ID
  sess: "m0wIPfpQHGc1QZXfI18juG", // Session ID
};

const jwtOptions = {
  keyid: "xxxxx", // kid
  algorithm: "RS256",
  audience: "https://widget.fitanalytics.com/api",
  issuer: "https://www.example.com",
  expiresIn: "48h",
  notBefore: "-1h",
};

const token = jwt.sign(payload, pemString, jwtOptions);

Sequence Diagrams

We are working on our API to create a smooth experience for partners, most of the endpoints that do not include the assets or serialized ids are going to be updated in the future.

Shopper tracking and sharing of session identifier through the API are managed in compliance with the partner implementation of GDPR regulations. The partner should consider handling the proper shopper consent before sending to us any shopper identifier through the API.

We refer to recommendations presented between screens throughout each flow as 'intermediate' or 'provisional' recommendations. These will not be as accurate or of the same high quality as the final recommendation displayed on the last screen.

Widget First Load
Widget common to all flows (Excluding shoes)
Widget lower flow (all genders)
Widget upper flow (woman)
Widget shoes (all genders)
Widget bra flow

3. API Usage Examples

For usage examples and live interaction with our API you can use our online tool: https://developers.fitanalytics.com/api/spec/

4. Customer IDs and profiles

In order to ensure Fit Finder can deliver personalized size recommendations throughout the shopper’s session, you must provide stable user identifiers (can be shop_session_id and/or user_id) we can use for tracking. Using a unique first-party session ID (Shop Session ID) that remains consistent throughout the whole duration of the session is essential for accurate and reliable tracking.

Customer identifiers

Our system recognizes three types of customer identifiers:

  1. Shop User ID: represents a customer that is registered with the client and is logged-in to the client's system on the API client (e.g. mobile device). The Shop User ID value should stay the same for the same customer between logins, and between different devices. It must not contain any personal identifiable information like for example an email address. Often referenced as shopUserId in the code or documentation.
  2. Shop Session ID: represents a unique session of the customer, regardless of their logged-in status. It should be present both for guests (ie. anonymous/non-logged-in customers) and for logged-in users. It should be unique for each device the customer uses the client's system on. It should preferably persist on the device between visits/interactions, where and if possible. Often referenced as shopSessionId in the code or documentation.
  3. Internal Session ID: in some cases it makes sense to include the internal Fit Analytics session ID. This ID is usually generated and stored by the Fit Finder widget on the client's website. The most common use-case for including the Internal Session ID is to share sessions between the Fit Finder widget and requests to the Fit Analytics API on the same page. Usually referenced as the sessionId in the code or documentation.

The Shop Session ID (SSID) must meet the following criteria and should only be shared when users have explicitly consented to analytics cookies:

  • Persistence: The SSID must remain unchanged regardless of whether a user logs in or out.
  • Accessibility: The same SSID must be accessible on the Product Detail Page (PDP), Order Confirmation Page (OCP), and, if applicable, Product Listing Page (PLP).
  • Anonymity: The SSID must not contain any personally identifiable information (PII).
  • Longevity: Ideally, the SSID should refresh only after 13 months of inactivity.

Technical Requirements

  • The SSID must be unique per visitor and remain consistent throughout a session.
  • It must be independent of the login status (i.e., remain the same when a user logs in or out).
  • The SSID must be accessible on PDP, OCP, and PLP (if applicable) and maintain the same value across all pages.
  • The SSID must not contain PII and should be different from your internal session ID (e.g., by hashing or encrypting your internal ID).
  • The SSID is provided under the FitA data object with the property "shopSessionId".
  • If using an object is not feasible, the ID should be shared via a JavaScript-readable source (avoiding cookies with the httpOnly flag).
  • The SSID should follow the UUID format (e.g., 123e4567-e89b-12d3-a456-426655440000), but we also support IDs up to 40 characters using A-Z, a-z, 0-9, -, _, @, #, $, %, ^, &.”

Customer records and profiles

When customers interact with the store, one of the usual scenarios is the following: an anonymous customer begins to browse the client's store and may try to add their inputs for a size recommendation. They're not logged-in at the time so only their session ID is present. Later, they log in and/or register (usually before the checkout) and their shop user ID is added into requests (in the token). Later they may log in and access the store from a different device under the same account and their previous inputs should be present and preferably already used for recommendations. The Fit Analytics service tries to resolve this scenario and many others in the following way:

  • It stores all the customer's input in one or more records. Each customer record may contain one or more profiles. Each profile is assigned a garment gender (where the value is one of: m/w/b/g ) and contains a set of customer's inputs. There's always exactly one profile that is marked as primary within each garment gender group, either explicitly with isPrimary attribute or implicitly by heuristic. The primary profile is used as a default profile in situations where the exact profile ID isn't explicitly specified. It's also useful when the user creates one or more different profiles and is able to switch between them through the user interface.
  • When working with profiles the combination of customer identifiers present in the token determines which records are taken into account. When the Shop User ID is present it will be used for accessing and managing a separate customer record (the "user-record") and when the Shop Session ID or the Internal Session ID is present it will be used for access to another record (the "session-record").
  • When both types of identifiers are present then both types of records are accessed. The system tries to synchronize both records by merging individual profiles and fields and keeping them up-to-date. The exact rules for merging records and profile are relatively complex, however in general the information from "user-record" takes precedence over the information in the "session-record".

5. Recommendation Event Sharing

When reporting recommendation events, you must differentiate between full and immediate recommendations to ensure these align with the correct stage in the shopper's journey. This differentiation helps create a seamless shopping experience and ensures accurate recommendations.

Event Classification

  • Full Recommendation → Provided at the end of the Fit Finder flow after a shopper enters all required inputs on a specific PDP.
  • Immediate Recommendation → Provided directly on the PDPs for returning shoppers without requiring them to click on the Fit Finder button or go through the widget flow again.

Implementation

  • If the recommendation is immediate, set "isImmediate": true in the recommendation call.
  • If it is a full recommendation, set "isImmediate": false.

Native App Onboarding Use Case

  • If Fit Finder is integrated into the onboarding process of a native app, all recommendations should be marked as immediate ("isImmediate": true).

6. Purchase events reporting

To ensure that our algorithms can continue to learn from your shoppers’ behaviour and that we can provide accurate reporting, you must set up purchase data sharing according to the Fit Finder API specifications.

The purchase data must include the shop session identifier (SSID) mentioned in the User Identification and Session Tracking above and also specify the platform type in the following format:

  • desktop
  • mobile_web
  • app

You can try our endpoint in our online tool: https://developers.fitanalytics.com/api/spec/

7. API policy and backwards compatibility

Wherever possible, our APIs will be maintained in a backwards compatible way. All of our API resources are versioned and the version is specified with the counter prefix in the resource path, e.g. /api/v1/resource. We're currently using prefix v1 everywhere. If it is necessary to change an endpoint in a way that it is not backwards compatible (see Breaking Changes for more info) i.e. it involves a breaking change, a new version of the resource will be created and the old version will be maintained for a specific period.

What CAN change

  • New features that can optionally be used (e.g. optional parameters in the body or new filters) that do not affect the existing behavior of the API. These do not require any updates by the consumers.
  • Fixes and changes to existing APIs that do not require any change from the consumer (e.g. changes in some optional response headers or some optimizations from our end)
  • New optional fields in the response that do not alter the original behavior of the API, but offer some more information if needed.
  • New optional headers that may be used for some additional filtering or triggers.
  • Fixes of bugs and updates to align discrepancies from our existing specifications. In the event that the API is not working as documented or as generally expected, we can fix the API to comply to its original intended behavior. This is not considered a breaking change and may require changes from the consumer. In the event of such a change, the consumers will be duly notified.

What will NOT change

  • API naming conventions. We will not alter the names of existing endpoints, rather add new ones as necessary.
  • API status codes and error codes. We will ensure the existing API behaves as documented.
  • Request body and headers. We will not introduce new required fields or headers in the API.
  • API response format and the mandatory response fields. We will not alter the response format and the mandatory fields already present.

Any change that does not comply to the above will be considered a breaking change.

Breaking changes

Significant changes to the API that would break the implementation of the consumer are considered breaking changes, some of them may be

  • Removing or renaming of API params.
  • Changes in the behavior of an existing endpoint
  • Changes in error codes or HTTP status codes.
  • Deprecating existing endpoints.

Creating new version of a resource is our way of handling of breaking changes. In the event of a breaking change, a deprecation notice along with a relevant migration guide will be published for a seamless transition. During the course of the transition period, we will maintain both the older version and the newer version of the resource until a deprecation date, after which the older version will be unsupported and will eventually be discontinued.