NAV

Introduction

Welcome to Velou!

The Velou REST API allows you interact directly with Velou to efficiently index your products and perform lightning fast, highly relevant search through your products catalog.

Ready to see it in action? Let's get going!

Getting Started

Velou API provides you with a variety of endpoints to craft intuitive, relevant and powerful search experiences to help your shopper's quickly find what they are looking for.

Formats

All API requests should be JSON encoded as UTF-8. The body of POST and PUT requests must be either a JSON object or a JSON array and their Content-Type header should be set to application/json. The body of responses is always a JSON object, and their content type is always application/json.

Versioning

API releases are versioned using a two part versioning scheme: {major version}.{minor version}. We broadly follow Semantic Versioning principles when versioning the API. The major version number is incremented when a backwards-incompatible change occurs. Minor version numbers are incremented when backwards-compatible changes occur.

Velou API versions are explicitly declared in the URL that your application calls: https://{API_HOST}/{version}

There are several supported versions of the APIs available, and you specify the version that you want to use by substituting the version name in the URL.

Version Release Date Changelog
0.9 March 5, 2019 Beta release
1.0 April 14, 2019 Initial stable version
1.1 June 25, 2019 Introduced facets support
1.2 October 10, 2019 Event tracking improvements (Usage Analytics)
1.3 November 15, 2021 Introducing new attributes: relatedIds, fitInformation, media.highResUrl, media.altText and collections
1.4 January 23, 2022 Incorporation of the analytics events for “add to cart”, and “promotions”
1.5 September 18, 2023 Modification for analytics to support multiple regions and languages
1.6 March 25, 2024 Incorporation of the analytics events for “complete the look”
1.7 December 23, 2024 Modified exporter response to include display names, synonyms, and trends
1.8 June 6, 2025 Standardized identifier naming by capitalizing the first letter of UserId and SessionId
1.9 October 10, 2025 Revised Public Indexing API definitions, including updates to the tags array
2.0 February 17, 2026 Added new v2/products endpoint with updated validations including variationId checks

Authentication

Accessing the Velou API requires the following; these credentials will be provided to you by Velou once your account is established.

Velou API uses key-based authentication over SSL. Every request must include the X-Velou-API-Key header.

Indexing

Add/Update Product

Velou provides an API for indexing products in your catalog. Use these endpoints to add new products or update existing ones. The API is asynchronous - you'll receive a unique task identifier to track the indexing status.

Consider invoking this API whenever:

Available Endpoints

Velou supports two API versions for product indexing:

Required Headers:

Authentication & store resolution: Requests are authenticated at the API gateway using the X-Velou-API-Key header. The key must belong to a consumer in the admin access group (indexing is a write operation). Your store is resolved automatically from the API key — you do not send a separate store identifier to these endpoints. As a result:

Use the v2 endpoint for all new integrations. The v1 endpoint remains active but is deprecated and may be removed in a future release.

Validation Behavior

Both endpoints validate the request body against a strict JSON Schema. Two behaviors are worth noting:

A failed validation returns HTTP 409 Conflict (see Error Responses). All validation errors are collected and returned together.

Version 1.0 Endpoint Details (Deprecated)

Endpoint: POST https://{API_HOST}/products

Required Fields

Every product indexing request must include:

All other fields are optional but highly recommended for optimal search relevance and user experience.

Quick Start

Minimal Request (required fields only)

{
  "id": "PROD123",
  "url": "https://mystore.com/products/red-dress",
  "skus": [
    {
      "price": 79.99
    }
  ]
}

Sample Response

{
  "success": true,
  "taskId": "652f8a1c9d4b2e0017a3c5e9"
}

Complete Product Object

Top-Level Fields

Field Type Required Length/Range Description
id String Yes 1-200 chars Unique product identifier from your system
url String Yes 1-2000 chars Product page URL (must be valid URI format)
skus Array Yes 1-200 items Product SKU variations (see SKU Object below)
name String No 1-500 chars Product display name
brand String No 1-200 chars Brand or manufacturer name
slug String No 1-300 chars URL-friendly product identifier
description String No 1-10,000 chars Detailed product description (HTML allowed)
categories Array[String] No 1-100 items, 1-200 chars each Product categories/hierarchy
collections Array[String] No 1-100 items, 1-200 chars each Collection/group membership
gender String No Enum Men, Women, or Unisex
ageGroup String No Enum Adults, Teens, or Kids
features Array[String] No 1-50 items, 1-2000 chars each Key features/bullet points
tags Array[String] No 1-2000 items, 1-1000 chars each Product tags (format: tagType:value)
customUserTags Array[String] No 1-200 items, 1-200 chars each Custom tags (format: tagType:value)
customUserData Object No Each value is an array of 1-30 strings (1-100 chars each); keys should match ^[a-zA-Z][a-zA-Z0-9]{0,30}$ Custom attributes
relatedIds Array[String] No 0-1000 items, 1-200 chars each IDs of related products
sortOrder Integer No - Custom sort order
arrivalDateTs Integer No - Arrival date (UNIX timestamp in ms)
media Array[Object] No 1-150 items Product images/videos (see Media Object)
variations Array[Object] No 1-50 items Color/style variations (see Variation Object)
fitInformation Array[String] No 1-20 items, 1-200 chars each Fit/sizing information
popularity Object No - Popularity metrics (see Popularity Object)

Nested Objects

SKU Object

Example

{
  "price": 79.99,
  "promoPrice": 59.99,
  "variationId": "red",
  "size": "Medium",
  "availability": "InStock",
  "inventoryQuantity": 45
}

Each item in the skus array represents a product variant (size, color combination, etc.).

Field Type Required Constraints Description
price Number Yes >= 0 Current selling price
id String No 1-200 chars SKU identifier (must be unique across all SKUs if provided)
variationId String No 1-200 chars Links to variations[].id
size String No 1-1000 chars Size designation (e.g., "Small", "10", "XL")
promoPrice Number No >= 0 Promotional/sale price
initialPrice Number No >= 0 Original/MSRP price before any discounts
estimatedRetailPrice Number No >= 0 Manufacturer's suggested retail price
inventoryQuantity Integer No >= 0 Current stock quantity
availability String No Enum See availability values below
condition Array[String] No 1-20 items, 1-200 chars each Product condition (e.g., "New", "Refurbished")
tags Array[String] No 1-100 items, 1-200 chars each SKU-specific tags (format: tagType:value)
options Array[String] No 1-300 items, 1-200 chars each SKU options (format: optionType:value)
mediaIds Array[String] No 1-100 items, 1-200 chars each IDs of media objects associated with this SKU

Availability Values:

Media Object

Example

{
  "url": "https://cdn.mystore.com/products/dress-red-500.jpg",
  "highResUrl": "https://cdn.mystore.com/products/dress-red-2000.jpg",
  "altText": "Woman wearing red floral dress with V-neck and long sleeves",
  "variationId": "red",
  "type": "image",
  "isPrimary": true,
  "order": 1
}

Each item in the media array represents an image or video.

Field Type Required Constraints Description
url String Yes 1-2000 chars, URI format Image/video URL
id String No 1-1000 chars Media identifier (must be unique across all media if provided)
highResUrl String No 1-2000 chars, URI format High-resolution version URL
altText String No 1-500 chars Accessibility description
variationId String No 1-200 chars Links to variations[].id
type String No Enum Media type: image or video
isPrimary Boolean No - Whether this is the primary media item
order Integer No >= 1 Display order (1-based)

Variation Object

Example

{
  "id": "red",
  "name": "Red",
  "swatch": "https://cdn.mystore.com/swatches/red.png",
  "url": "https://mystore.com/products/floral-dress?color=red"
}

Each item in the variations array represents a color or style variant.

Field Type Required Constraints Description
id String Yes 1-200 chars Unique variation identifier
name String Yes 1-150 chars Variation name (e.g., "Red", "Navy Blue")
swatch String No 1-500 chars, URI format Color swatch image URL
url String No 1-2000 chars Variation-specific product URL
productId String No 1-200 chars Variation product identifier
productName String No 1-500 chars Variation-specific product name
relatedIds Array[String] No 0-300 items, 1-200 chars each Related variation IDs
type String No 1-100 chars Variation type descriptor (e.g., "color", "style")

Popularity Object

Type: STAR (Star Rating System)

{
  "type": "STAR",
  "data": {
    "overallRating": 4.3,           // Required: Number >= 0
    "maxRating": 5,                 // Required: Number >= 0
    "reviewCount": 260,             // Required: Integer >= 0
    "ratingSummary": [              // Optional: Array, 0-10 items
      {
        "rating": 5,                // Required: Integer >= 1
        "count": 120                // Required: Integer >= 0
      },
      {
        "rating": 4,
        "count": 85
      }
    ]
  }
}

Type: LIKES (Like/Favorite Count)

{
  "type": "LIKES",
  "data": {
    "favLikeCount": 1250            // Required: Integer >= 0
  }
}

Type: THUMBS (Thumbs Up/Down)

{
  "type": "THUMBS",
  "data": {
    "thumbsUpCount": 89,            // Required: Integer >= 0
    "thumbsDownCount": 12           // Required: Integer >= 0
  }
}

The popularity object structure depends on the type field.

Special Format Requirements

Tag Format

Tags and custom user tags must follow the tagType:value format:

Valid Example

"tags": [
  "color:Red",
  "neckline:V-Neck",
  "fit_type:Relaxed",
  "material:Cotton",
  "sleeve_length:Long"
]

Invalid Example

"tags": [
  "Red",         // No colon, so no tag type
  "color-Red",   // Hyphen is not a valid separator
  ":Red",        // Empty tag type before the colon
  "color:"       // Nothing after the colon
]

The tag type (before the colon) must be one or more of [a-zA-Z0-9_], followed by : and at least one character. The check is a substring match (it is not anchored), so a value such as "neckline: V-Neck" — including the space after the colon — passes validation.

Applies to: tags[], customUserTags[], skus[].tags[]. (skus[].options[] follow the same optionType:value pattern.)

Custom User Data Keys

Custom user data object keys should match the pattern ^[a-zA-Z][a-zA-Z0-9]{0,30}$ — start with a letter (A–Z or a–z), followed by up to 30 letters or digits. Each value must be an array of 1–30 strings, each 1–100 characters.

Valid Example

"customUserData": {
  "seasonalCollection": ["Summer2025", "Resort"],
  "exclusiveRetailer": ["NordstromExclusive"],
  "certifications": ["Organic", "FairTrade"]
}

Discouraged Keys (do not follow the recommended pattern)

"customUserData": {
  "seasonal-collection": ["Resort"],   // Hyphen not in pattern
  "1stPlace": ["Winner"],              // Starts with a number
  "_private": ["Hidden"]               // Starts with an underscore
}

Complete Example

Full Product Request

{
  "id": "1636730011711",
  "url": "https://demostore.com/products/floral-red-dress",
  "name": "Floral Red Dress - V-Neck Sleeveless Summer Collection",
  "brand": "Dress Forum",
  "slug": "floral-red-dress-v-neck-sleeveless",
  "description": "Ever comfortable and chic, the classic shift gains a fresh feeling from crisp, colorful crepe. Perfect for summer occasions.",
  "features": [
    "34 1/2\" length (size Medium)",
    "Exposed back-zip closure",
    "97% polyester, 3% spandex",
    "Hand wash cold, dry flat",
    "Imported"
  ],
  "categories": [
    "Women",
    "Clothing",
    "Dresses",
    "Casual Dresses"
  ],
  "collections": [
    "Summer 2025",
    "Resort Collection"
  ],
  "gender": "Women",
  "ageGroup": "Adults",
  "relatedIds": ["1636730011712", "1636730011713"],
  "arrivalDateTs": 1625097600000,
  "variations": [
    {
      "id": "red",
      "name": "Red",
      "swatch": "https://demostore.com/images/swatches/red.png",
      "url": "https://demostore.com/products/floral-red-dress?color=red"
    },
    {
      "id": "black",
      "name": "Black",
      "swatch": "https://demostore.com/images/swatches/black.png",
      "url": "https://demostore.com/products/floral-red-dress?color=black"
    }
  ],
  "media": [
    {
      "url": "https://demostore.com/images/products/l/1636730011711-red-front.jpg",
      "highResUrl": "https://demostore.com/images/products/xl/1636730011711-red-front.jpg",
      "altText": "Front view of red floral dress with V-neck and sleeveless design",
      "variationId": "red"
    },
    {
      "url": "https://demostore.com/images/products/l/1636730011711-red-back.jpg",
      "highResUrl": "https://demostore.com/images/products/xl/1636730011711-red-back.jpg",
      "altText": "Back view showing exposed zipper closure",
      "variationId": "red"
    },
    {
      "url": "https://demostore.com/images/products/l/1636730011711-black-front.jpg",
      "highResUrl": "https://demostore.com/images/products/xl/1636730011711-black-front.jpg",
      "altText": "Front view of black floral dress with V-neck and sleeveless design",
      "variationId": "black"
    }
  ],
  "skus": [
    {
      "price": 79.99,
      "promoPrice": 59.99,
      "initialPrice": 99.99,
      "variationId": "red",
      "size": "Small",
      "availability": "InStock",
      "inventoryQuantity": 25
    },
    {
      "price": 79.99,
      "promoPrice": 59.99,
      "variationId": "red",
      "size": "Medium",
      "availability": "InStock",
      "inventoryQuantity": 40
    },
    {
      "price": 79.99,
      "variationId": "red",
      "size": "Large",
      "availability": "LimitedAvailability",
      "inventoryQuantity": 3
    },
    {
      "price": 79.99,
      "variationId": "black",
      "size": "Small",
      "availability": "InStock",
      "inventoryQuantity": 18
    }
  ],
  "tags": [
    "color:Red",
    "neckline:V-Neck",
    "fit_type:Relaxed",
    "sleeve_length:Sleeveless",
    "occasion:Casual",
    "season:Summer",
    "pattern:Floral"
  ],
  "customUserTags": [
    "collection:Resort2025",
    "trending:SummerEssentials"
  ],
  "fitInformation": [
    "True to size",
    "Model is 5'9\" and wearing size Small",
    "Relaxed fit through body"
  ],
  "popularity": {
    "type": "STAR",
    "data": {
      "overallRating": 4.3,
      "maxRating": 5,
      "reviewCount": 260,
      "ratingSummary": [
        { "rating": 5, "count": 140 },
        { "rating": 4, "count": 80 },
        { "rating": 3, "count": 25 },
        { "rating": 2, "count": 10 },
        { "rating": 1, "count": 5 }
      ]
    }
  }
}

Sample Response

{
  "success": true,
  "taskId": "652f8a1c9d4b2e0017a3c5e9"
}

Use the taskId to track indexing status via the Task Tracking endpoint.

Error Responses

409 Conflict — Validation Error

When request validation fails, the API responds with HTTP status 409 Conflict and a body in the following shape. The errors array contains the raw validator errors (one entry per failed constraint, since all errors are collected). Each entry includes an instancePath pointing to the offending field, the failing keyword, validator params, and a human-readable message.

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/url",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/url", "keyword": "format", "params": { "format": "uri-reference" } }
        ]
      },
      "message": "url should be a string (minLength=1, maxLength=2000) and should conform to valid URI format"
    },
    {
      "instancePath": "/skus",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/skus", "keyword": "minItems", "params": { "limit": 1 } }
        ]
      },
      "message": "skus should be an array of valid Sku objects (minItems=1, maxItems=200). Please refer API documentation for more info."
    }
  ],
  "message": "Validation failure"
}

Common Validation Errors

Missing Required Field (id)

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "",
      "keyword": "required",
      "params": { "missingProperty": "id" },
      "message": "must have required property 'id'"
    }
  ],
  "message": "Validation failure"
}

Invalid Enum Value (gender)

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/gender",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/gender", "keyword": "enum", "params": { "allowedValues": ["Men", "Women", "Unisex"] } }
        ]
      },
      "message": "gender should be a string (allowed_values=Men|Women|Unisex)"
    }
  ],
  "message": "Validation failure"
}

Invalid Tag Format (tags[0])

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/tags/0",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/tags/0", "keyword": "pattern", "params": { "pattern": "[a-zA-Z0-9_]+:.+" } }
        ]
      },
      "message": "tags should be an array of strings (minItems=1,maxItems=2000,minLength=1,maxLength=1000) and should conform to 'tagType:tag' format"
    }
  ],
  "message": "Validation failure"
}

Unknown Additional Property

Sending any field not defined in the schema causes a top-level additionalProperties error. The additionalProperty param names the offending key.

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "",
      "keyword": "additionalProperties",
      "params": { "additionalProperty": "unknownField" },
      "message": "must NOT have additional properties"
    }
  ],
  "message": "Validation failure"
}

Authentication & Authorization Errors

These are returned by the API gateway before the request reaches the indexing service.

401 Unauthorized (missing API key)

{ "message": "No API key found in request" }

401 Unauthorized (invalid API key)

{ "message": "Invalid authentication credentials" }

403 Forbidden (key lacks admin permissions)

{ "message": "You cannot consume this service" }

If the API key is valid but its store is not provisioned/active, the service responds with:

401 Unauthorized (unknown store)

{
  "code": "Unauthorized",
  "message": "Store Id not found. Please contact Velou"
}

Best Practices For Product Indexing

Data Quality

Field Usage

URLs (up to 2000 characters): - Use absolute URLs, not relative paths - Include tracking parameters (UTM codes, session IDs, etc.) as needed - Ensure URLs are properly URL-encoded - Example: https://store.com/products/dress?utm_source=email&color=red

Product Names (up to 500 characters): - Include key specifications and descriptors - Front-load important information - Example: "Nike Women's Air Zoom Pegasus 38 - Breathable Mesh Running Shoes - Black/White"

IDs (up to 200 characters): - Supports composite keys, hierarchical identifiers, UUIDs - Use consistent ID structure across your catalog - Example: "store_123_category_shoes_product_abc789"

Descriptions (up to 10,000 characters): - Be comprehensive - include materials, care instructions, features - HTML formatting is supported - Break into paragraphs for readability

Arrays

Categories: - Provide full category hierarchy: ["Women", "Clothing", "Dresses", "Casual Dresses"] - Use 1-100 items, each up to 200 characters - Consistent naming improves faceted search

Tags: - Always use tagType:value format: "color:Red" not "Red" - Use consistent tag types: color, size, material, style, occasion - Supports 1-2000 tags, each up to 1000 characters - More tags = better discoverability

Media: - Provide images for all variations - Use variationId to link images to color/style variants - Include descriptive altText for accessibility (up to 500 chars) - High-res URLs improve image search capabilities

Features: - Use for bullet points and key highlights - Each feature can be up to 2000 characters - Include specifications, materials, dimensions, care instructions

Variations & SKUs

Linking Variations: - Define variations with unique IDs: {id: "red", name: "Red"} - Link SKUs to variations: {variationId: "red", size: "Small"} - Link media to variations: {url: "...", variationId: "red"} - Ensures proper filtering and display

SKU Management: - Keep availability status current - Update inventoryQuantity regularly - Use promoPrice for sale pricing - Include size information when applicable

Performance

Error Handling For Product Indexing

Quick Reference Card

Required Fields

Common Field Limits

Enum Fields

Array Limits

Special Formats

Version 2.0 Endpoint Details

Endpoint: POST https://{API_HOST}/v2/products

Required Fields

Every product indexing request must include:

All other fields are optional but highly recommended for optimal search relevance and user experience.

Quick Start

Minimal Request (required fields only)

{
  "id": "PROD123",
  "url": "https://mystore.com/products/red-dress",
  "skus": [
    {
      "variationId": "red",
      "price": 79.99
    }
  ],
  "variations": [
    {
      "id": "red",
      "name": "Red"
    }
  ]
}

Sample Response

{
  "success": true,
  "taskId": "652f8a1c9d4b2e0017a3c5e9"
}

Complete Product Object

Top-Level Fields

Field Type Required Length/Range Description
id String Yes 1-200 chars Unique product identifier from your system
url String Yes 1-2000 chars Product page URL (must be valid URI format)
skus Array Yes 1-300 items Product SKU variations (see SKU Object below)
name String No 1-500 chars Product display name
brand String No 1-200 chars Brand or manufacturer name
slug String No 1-300 chars URL-friendly product identifier
description String No 1-10,000 chars Detailed product description (HTML allowed)
categories Array[String] No 1-100 items, 1-200 chars each Product categories/hierarchy
collections Array[String] No 1-100 items, 1-200 chars each Collection/group membership
gender String No Enum Men, Women, or Unisex
ageGroup String No Enum Adults, Teens, or Kids
features Array[String] No 1-50 items, 1-2000 chars each Key features/bullet points
tags Array[String] No 1-2000 items, 1-1000 chars each Product tags (format: tagType:value)
customUserTags Array[String] No 1-200 items, 1-200 chars each Custom tags (format: tagType:value)
customUserData Object No Each value is an array of 1-30 strings (1-100 chars each); keys should match ^[a-zA-Z][a-zA-Z0-9]{0,30}$ Custom attributes
relatedIds Array[String] No 0-1000 items, 1-200 chars each IDs of related products
sortOrder Integer No - Custom sort order
arrivalDateTs Integer No - Arrival date (UNIX timestamp in ms)
media Array[Object] No 1-150 items Product images/videos (see Media Object)
variations Array[Object] Yes 1-50 items Color/style variations (see Variation Object)
fitInformation Array[String] No 1-20 items, 1-200 chars each Fit/sizing information
popularity Object No - Popularity metrics (see Popularity Object)

Nested Objects

SKU Object

Example

{
  "price": 79.99,
  "promoPrice": 59.99,
  "variationId": "red",
  "size": "Medium",
  "availability": "InStock",
  "inventoryQuantity": 45
}

Each item in the skus array represents a product variant (size, color combination, etc.).

Field Type Required Constraints Description
price Number Yes >= 0 Current selling price
variationId String Yes 1-200 chars Links to variations[].id
id String No 1-200 chars SKU identifier (must be unique across all SKUs if provided)
size String No 1-1000 chars Size designation (e.g., "Small", "10", "XL")
promoPrice Number No >= 0 Promotional/sale price
initialPrice Number No >= 0 Original/MSRP price before any discounts
estimatedRetailPrice Number No >= 0 Manufacturer's suggested retail price
inventoryQuantity Integer No >= 0 Current stock quantity
availability String No Enum See availability values below
condition Array[String] No 1-20 items, 1-200 chars each Product condition (e.g., "New", "Refurbished")
tags Array[String] No 1-100 items, 1-200 chars each SKU-specific tags (format: tagType:value)
options Array[String] No 1-300 items, 1-200 chars each SKU options (format: optionType:value)
mediaIds Array[String] No 1-100 items, 1-200 chars each IDs of media objects associated with this SKU

Availability Values:

Media Object

Example

{
  "url": "https://cdn.mystore.com/products/dress-red-500.jpg",
  "highResUrl": "https://cdn.mystore.com/products/dress-red-2000.jpg",
  "altText": "Woman wearing red floral dress with V-neck and long sleeves",
  "variationId": "red",
  "type": "image",
  "isPrimary": true,
  "order": 1
}

Each item in the media array represents an image or video.

Field Type Required Constraints Description
url String Yes 1-2000 chars, URI format Image/video URL
id String No 1-1000 chars Media identifier (must be unique across all media if provided)
highResUrl String No 1-2000 chars, URI format High-resolution version URL
altText String No 1-500 chars Accessibility description
variationId String No 1-200 chars Links to variations[].id
type String No Enum Media type: image or video
isPrimary Boolean No - Whether this is the primary media item
order Integer No >= 1 Display order (1-based)

Variation Object

Each item in the variations array represents a color or style variant.

Example

{
  "id": "red",
  "name": "Red",
  "swatch": "https://cdn.mystore.com/swatches/red.png",
  "url": "https://mystore.com/products/floral-dress?color=red"
}
Field Type Required Constraints Description
id String Yes 1-200 chars Unique variation identifier
name String Yes 1-150 chars Variation name (e.g., "Red", "Navy Blue")
swatch String No 1-500 chars, URI format Color swatch image URL
url String No 1-2000 chars Variation-specific product URL
productId String No 1-200 chars Variation product identifier
productName String No 1-500 chars Variation-specific product name
relatedIds Array[String] No 0-300 items, 1-200 chars each Related variation IDs
type String No 1-100 chars Variation type descriptor (e.g., "color", "style")

Popularity Object

The popularity object structure depends on the type field.

Type: STAR (Star Rating System)

{
  "type": "STAR",
  "data": {
    "overallRating": 4.3,           // Required: Number >= 0
    "maxRating": 5,                 // Required: Number >= 0
    "reviewCount": 260,             // Required: Integer >= 0
    "ratingSummary": [              // Optional: Array, 0-10 items
      {
        "rating": 5,                // Required: Integer >= 1
        "count": 120                // Required: Integer >= 0
      },
      {
        "rating": 4,
        "count": 85
      }
    ]
  }
}

Type: LIKES (Like/Favorite Count)

{
  "type": "LIKES",
  "data": {
    "favLikeCount": 1250            // Required: Integer >= 0
  }
}

Type: THUMBS (Thumbs Up/Down)

{
  "type": "THUMBS",
  "data": {
    "thumbsUpCount": 89,            // Required: Integer >= 0
    "thumbsDownCount": 12           // Required: Integer >= 0
  }
}

Special Format Requirements

Tag Format

Tags and custom user tags must follow the tagType:value format:

Valid Example

"tags": [
  "color:Red",
  "neckline:V-Neck",
  "fit_type:Relaxed",
  "material:Cotton",
  "sleeve_length:Long"
]

Invalid Example

"tags": [
  "Red",         // No colon, so no tag type
  "color-Red",   // Hyphen is not a valid separator
  ":Red",        // Empty tag type before the colon
  "color:"       // Nothing after the colon
]

The tag type (before the colon) must be one or more of [a-zA-Z0-9_], followed by : and at least one character. The check is a substring match (it is not anchored), so a value such as "neckline: V-Neck" — including the space after the colon — passes validation.

Applies to: tags[], customUserTags[], skus[].tags[]. (skus[].options[] follow the same optionType:value pattern.)

Custom User Data Keys

Custom user data object keys should match the pattern ^[a-zA-Z][a-zA-Z0-9]{0,30}$ — start with a letter (A–Z or a–z), followed by up to 30 letters or digits. Each value must be an array of 1–30 strings, each 1–100 characters.

Valid Example

"customUserData": {
  "seasonalCollection": ["Summer2025", "Resort"],
  "exclusiveRetailer": ["NordstromExclusive"],
  "certifications": ["Organic", "FairTrade"]
}

Discouraged Keys (do not follow the recommended pattern)

"customUserData": {
  "seasonal-collection": ["Resort"],   // Hyphen not in pattern
  "1stPlace": ["Winner"],              // Starts with a number
  "_private": ["Hidden"]               // Starts with an underscore
}

Complete Example

Full Product Request

{
  "id": "1636730011711",
  "url": "https://demostore.com/products/floral-red-dress",
  "name": "Floral Red Dress - V-Neck Sleeveless Summer Collection",
  "brand": "Dress Forum",
  "slug": "floral-red-dress-v-neck-sleeveless",
  "description": "Ever comfortable and chic, the classic shift gains a fresh feeling from crisp, colorful crepe. Perfect for summer occasions.",
  "features": [
    "34 1/2\" length (size Medium)",
    "Exposed back-zip closure",
    "97% polyester, 3% spandex",
    "Hand wash cold, dry flat",
    "Imported"
  ],
  "categories": [
    "Women",
    "Clothing",
    "Dresses",
    "Casual Dresses"
  ],
  "collections": [
    "Summer 2025",
    "Resort Collection"
  ],
  "gender": "Women",
  "ageGroup": "Adults",
  "relatedIds": ["1636730011712", "1636730011713"],
  "arrivalDateTs": 1625097600000,
  "variations": [
    {
      "id": "red",
      "name": "Red",
      "swatch": "https://demostore.com/images/swatches/red.png",
      "url": "https://demostore.com/products/floral-red-dress?color=red"
    },
    {
      "id": "black",
      "name": "Black",
      "swatch": "https://demostore.com/images/swatches/black.png",
      "url": "https://demostore.com/products/floral-red-dress?color=black"
    }
  ],
  "media": [
    {
      "url": "https://demostore.com/images/products/l/1636730011711-red-front.jpg",
      "highResUrl": "https://demostore.com/images/products/xl/1636730011711-red-front.jpg",
      "altText": "Front view of red floral dress with V-neck and sleeveless design",
      "variationId": "red"
    },
    {
      "url": "https://demostore.com/images/products/l/1636730011711-red-back.jpg",
      "highResUrl": "https://demostore.com/images/products/xl/1636730011711-red-back.jpg",
      "altText": "Back view showing exposed zipper closure",
      "variationId": "red"
    },
    {
      "url": "https://demostore.com/images/products/l/1636730011711-black-front.jpg",
      "highResUrl": "https://demostore.com/images/products/xl/1636730011711-black-front.jpg",
      "altText": "Front view of black floral dress with V-neck and sleeveless design",
      "variationId": "black"
    }
  ],
  "skus": [
    {
      "price": 79.99,
      "promoPrice": 59.99,
      "initialPrice": 99.99,
      "variationId": "red",
      "size": "Small",
      "availability": "InStock",
      "inventoryQuantity": 25
    },
    {
      "price": 79.99,
      "promoPrice": 59.99,
      "variationId": "red",
      "size": "Medium",
      "availability": "InStock",
      "inventoryQuantity": 40
    },
    {
      "price": 79.99,
      "variationId": "red",
      "size": "Large",
      "availability": "LimitedAvailability",
      "inventoryQuantity": 3
    },
    {
      "price": 79.99,
      "variationId": "black",
      "size": "Small",
      "availability": "InStock",
      "inventoryQuantity": 18
    }
  ],
  "tags": [
    "color:Red",
    "neckline:V-Neck",
    "fit_type:Relaxed",
    "sleeve_length:Sleeveless",
    "occasion:Casual",
    "season:Summer",
    "pattern:Floral"
  ],
  "customUserTags": [
    "collection:Resort2025",
    "trending:SummerEssentials"
  ],
  "fitInformation": [
    "True to size",
    "Model is 5'9\" and wearing size Small",
    "Relaxed fit through body"
  ],
  "popularity": {
    "type": "STAR",
    "data": {
      "overallRating": 4.3,
      "maxRating": 5,
      "reviewCount": 260,
      "ratingSummary": [
        { "rating": 5, "count": 140 },
        { "rating": 4, "count": 80 },
        { "rating": 3, "count": 25 },
        { "rating": 2, "count": 10 },
        { "rating": 1, "count": 5 }
      ]
    }
  }
}

Sample Response

{
  "success": true,
  "taskId": "652f8a1c9d4b2e0017a3c5e9"
}

Use the taskId to track indexing status via the Task Tracking endpoint.

Error Responses

409 Conflict — Validation Error

When request validation fails, the API responds with HTTP status 409 Conflict. The body uses the same envelope as v1 — success: false, code: "InvalidArgument", a collected errors array, and message: "Validation failure". Schema-level errors carry an instancePath; v2's variation cross-checks (below) carry a dataPath instead.

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/url",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/url", "keyword": "format", "params": { "format": "uri-reference" } }
        ]
      },
      "message": "url should be a string (minLength=1, maxLength=2000) and should conform to valid URI format"
    },
    {
      "instancePath": "/skus",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/skus", "keyword": "minItems", "params": { "limit": 1 } }
        ]
      },
      "message": "skus should be an array of valid Sku objects (minItems=1, maxItems=300). Please refer API documentation for more info."
    }
  ],
  "message": "Validation failure"
}

Common Validation Errors

Missing Required SKU Field (variationId)

Every SKU in v2 must include variationId. Because the skus array has a top-level errorMessage override, the inner required-field error is wrapped — the outer entry lands at instancePath: "/skus" with keyword: "errorMessage", and the specific per-SKU error is inside params.errors:

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/skus",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          {
            "instancePath": "/skus/0",
            "keyword": "required",
            "params": { "missingProperty": "variationId" },
            "message": "must have required property 'variationId'"
          }
        ]
      },
      "message": "skus should be an array of valid Sku objects (minItems=1, maxItems=300). Please refer API documentation for more info."
    }
  ],
  "message": "Validation failure"
}

Invalid Enum Value (gender)

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/gender",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/gender", "keyword": "enum", "params": { "allowedValues": ["Men", "Women", "Unisex"] } }
        ]
      },
      "message": "gender should be a string (allowed_values=Men|Women|Unisex)"
    }
  ],
  "message": "Validation failure"
}

Unknown Additional Property

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "",
      "keyword": "additionalProperties",
      "params": { "additionalProperty": "unknownField" },
      "message": "must NOT have additional properties"
    }
  ],
  "message": "Validation failure"
}

Variation Cross-Field Errors (v2 only)

After schema validation passes, v2 performs an additional cross-check between skus[].variationId and the variations array. These errors use a dataPath field and the keyword variationIdMismatch.

variations array missing or empty (while SKUs carry variationId)

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "keyword": "variationIdMismatch",
      "dataPath": ".variations",
      "params": {},
      "message": "variations array must be present and contain ids matching all variationId values from skus"
    }
  ],
  "message": "Validation failure"
}

A variationId used in SKUs has no matching id in variations

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "keyword": "variationIdMismatch",
      "dataPath": ".skus",
      "params": { "missingVariationIds": ["red"] },
      "message": "variationId values [red] in skus must match an id in variations array"
    }
  ],
  "message": "Validation failure"
}

Authentication & Authorization Errors

Identical to the v1 endpoint: a missing key returns 401 ({ "message": "No API key found in request" }), an invalid key returns 401 ({ "message": "Invalid authentication credentials" }), and a key without admin permissions returns 403 ({ "message": "You cannot consume this service" }).

Best Practices For Product Indexing

Data Quality

Field Usage

URLs (up to 2000 characters): - Use absolute URLs, not relative paths - Include tracking parameters (UTM codes, session IDs, etc.) as needed - Ensure URLs are properly URL-encoded - Example: https://store.com/products/dress?utm_source=email&color=red

Product Names (up to 500 characters): - Include key specifications and descriptors - Front-load important information - Example: "Nike Women's Air Zoom Pegasus 38 - Breathable Mesh Running Shoes - Black/White"

IDs (up to 200 characters): - Supports composite keys, hierarchical identifiers, UUIDs - Use consistent ID structure across your catalog - Example: "store_123_category_shoes_product_abc789"

Descriptions (up to 10,000 characters): - Be comprehensive - include materials, care instructions, features - HTML formatting is supported - Break into paragraphs for readability

Arrays

Categories: - Provide full category hierarchy: ["Women", "Clothing", "Dresses", "Casual Dresses"] - Use 1-100 items, each up to 200 characters - Consistent naming improves faceted search

Tags: - Always use tagType:value format: "color:Red" not "Red" - Use consistent tag types: color, size, material, style, occasion - Supports 1-2000 tags, each up to 1000 characters - More tags = better discoverability

Media: - Provide images for all variations - Use variationId to link images to color/style variants - Include descriptive altText for accessibility (up to 500 chars) - High-res URLs improve image search capabilities

Features: - Use for bullet points and key highlights - Each feature can be up to 2000 characters - Include specifications, materials, dimensions, care instructions

Variations & SKUs

Linking Variations: - Define variations with unique IDs: {id: "red", name: "Red"} - Link SKUs to variations: {variationId: "red", size: "Small"} - Link media to variations: {url: "...", variationId: "red"} - Ensures proper filtering and display

SKU Management: - Keep availability status current - Update inventoryQuantity regularly - Use promoPrice for sale pricing - Include size information when applicable

Performance

Error Handling For Product Indexing

Quick Reference Card

Required Fields

Common Field Limits

Enum Fields

Array Limits

Special Formats

Delete Product

This API provides facility to delete an existing product from Velou index. It is important that you leverage this API to keep the Velou product index up-to-date at all times. Consider invoking this API whenever a product is removed from your product catalog. Please note that this API call is asynchronous. Once the API is invoked, you will receive an unique task identifier which you can use to track the status of the task.

Sample Request

curl -X DELETE 'https://{API_HOST}/products/1636730011711' \
  -H 'X-Velou-API-Key: <api-key-admin>'

Sample Response

{
  "success": true,
  "taskId": "652f8a1c9d4b2e0017a3c5e9"
}

Request

DELETE /products/{id}

Required API Key: admin

Parameter Type Description Default Example
id (URL) String Unique product identifier (1–50 characters). NULL 1636730011711

Response

Parameter Type Description
success Boolean Always true on success
taskId String Unique task identifier (24-character hexadecimal MongoDB ObjectId)

Error Responses

409 Conflict — Validation Error

ID exceeds 50 characters

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/id",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/id", "keyword": "maxLength", "params": { "limit": 50 } }
        ]
      },
      "message": "id should be a string (max_length=50)"
    }
  ],
  "message": "Validation failure"
}

Authentication & Authorization Errors

Identical to the indexing endpoints: a missing or invalid API key returns 401, a key without admin permissions returns 403.

Task Tracking

All asynchronous API calls supported by Velou during the product indexing returns a unique task identifier. Task tracking API is useful to understand the current status of each task you've queued on Velou indexing process. This API takes a unique task identifier as the input.

Sample Request

curl -X GET 'https://{API_HOST}/tasks/652f8a1c9d4b2e0017a3c5e9' \
  -H 'X-Velou-API-Key: <api-key-admin>'

Sample Response

{
  "status": "complete",
  "createdAt": "2026-06-03T16:21:00.480Z",
  "updatedAt": "2026-06-03T16:22:00.480Z"
}

Task Tracking Request

GET /tasks/{id}

Required API Key: admin

Parameter Type Description Default Example
id (URL) String Unique task identifier. Must be a 24-character hexadecimal MongoDB ObjectId ([0-9a-f]{24}) as returned by the index/delete endpoints. A malformed id is rejected with a 409 validation error ("Malformed task Id. Please use a task id returned by the index API"). NULL 652f8a1c9d4b2e0017a3c5e9

Task Tracking Response

Parameter Type Description
status Enum [pending, inprogress, complete, retry, error] Current status of the task
createdAt Date ISO 8601 timestamp at which the task was created
updatedAt Date ISO 8601 timestamp at which the task was last updated

Task status values:

Error Responses

409 Conflict — Malformed Task ID

The task ID must be a 24-character lowercase hexadecimal string (a MongoDB ObjectId). Anything else is rejected before the database is queried.

ID is not a 24-character hex string

{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/id",
      "keyword": "errorMessage",
      "params": {
        "errors": [
          { "instancePath": "/id", "keyword": "pattern", "params": { "pattern": "[0-9a-f]{24}" } }
        ]
      },
      "message": "Malformed task Id. Please use a task id returned by the index API"
    }
  ],
  "message": "Validation failure"
}

404 Not Found — Unknown or Purged Task

Returned when the ID is well-formed but no matching task exists for your store (including tasks that have been purged after their retention period).

Task not found

{
  "success": false,
  "code": "NotFound",
  "message": "Task 652f8a1c9d4b2e0017a3c5e9 not found in the system."
}

Searching

Search Results

Velou provides an API for searching the catalog of products indexed in your Velou account. The API provides the ability to return results based on a search query. The response will include data points to build a powerful search experience, such as products that match the search criteria, available facet options to further refine the results, spell correction suggestions and data useful for paginating the search results.

Sample Request

curl -X GET 'https://{API_HOST}/1.0/search?query=red%20long%20sleeve%20dress&from=100&pageSize=50&returnFacets=true&facets=color:red,sleeve_length:long&userId=51w0orqu5&sessionId=bd0fl9aoc' \
  -H 'X-Velou-API-Key: <api-key-search>'

Sample Response

{
  "totalProductCount": 1,
  "products": [
    {
      "id": "605a14affb1e95bd9cb37fba",
      "productId": "6158888960197",
      "url": "https://demo.velou.com/products/texas-rose-plus",
      "name": "Texas Rose - Plus",
      "designer": "Bali ELF",
      "price": {
        "min": 139.95,
        "max": 139.95
      },
      "promoPrice": {
        "min": 0,
        "max": 0
      },
      "initialPrice": {
        "min": 186.95,
        "max": 186.95
      },
      "customProps": {},
      "defaultColorId": "2",
      "colors": {
        "1": {
          "name": "White",
          "swatch": "https://demo-images.velou.com/w_150/f_auto/q_auto/ar_0.66,c_fill/v1604012081/product-images-octo/labo5b0btg7sxlfpxavd.jpg",
          "images": [
            {
              "s": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604012081/product-images-octo/labo5b0btg7sxlfpxavd.jpg",
              "m": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604012081/product-images-octo/labo5b0btg7sxlfpxavd.jpg",
              "l": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604012081/product-images-octo/labo5b0btg7sxlfpxavd.jpg"
            }
          ],
          "values": [
            {
              "hex": "e0d3c3",
              "ratio": 50
            },
            {
              "hex": "d1c2a8",
              "ratio": 50
            }
          ],
          "productUrl": "https://demo.velou.com/products/texas-rose-plus?variant=37897423225029",
          "promoPrice": {
            "min": 0,
            "max": 0
          },
          "price": {
            "min": 139.95,
            "max": 139.95
          },
          "initialPrice": {
            "min": 186.95,
            "max": 186.95
          }
        },
        "2": {
          "name": "Ruby",
          "swatch": "https://demo-images.velou.com/w_150/f_auto/q_auto/ar_0.66,c_fill/v1604009390/product-images-octo/zfe71m3npqzc3jl5yxl5.jpg",
          "images": [
            {
              "s": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604009390/product-images-octo/zfe71m3npqzc3jl5yxl5.jpg",
              "m": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604009390/product-images-octo/zfe71m3npqzc3jl5yxl5.jpg",
              "l": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604009390/product-images-octo/zfe71m3npqzc3jl5yxl5.jpg"
            }
          ],
          "values": [
            {
              "hex": "4b0d1d",
              "ratio": 12
            },
            {
              "hex": "791e37",
              "ratio": 43
            },
            {
              "hex": "91354e",
              "ratio": 45
            }
          ],
          "productUrl": "https://demo.velou.com/products/texas-rose-plus?variant=37897423257797",
          "promoPrice": {
            "min": 0,
            "max": 0
          },
          "price": {
            "min": 139.95,
            "max": 139.95
          },
          "initialPrice": {
            "min": 186.95,
            "max": 186.95
          }
        },
        "3": {
          "name": "Navy Blue",
          "swatch": "https://demo-images.velou.com/w_150/f_auto/q_auto/ar_0.66,c_fill/v1604010964/product-images-octo/g4xdj4mmwksgzmezjjkw.jpg",
          "images": [
            {
              "s": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604010964/product-images-octo/g4xdj4mmwksgzmezjjkw.jpg",
              "m": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604010964/product-images-octo/g4xdj4mmwksgzmezjjkw.jpg",
              "l": "https://demo-images.velou.com/w_750/f_auto/q_auto/ar_0.66,c_fill/v1604010964/product-images-octo/g4xdj4mmwksgzmezjjkw.jpg"
            }
          ],
          "values": [
            {
              "hex": "0d1e36",
              "ratio": 30
            },
            {
              "hex": "36597c",
              "ratio": 17
            },
            {
              "hex": "8e969d",
              "ratio": 53
            }
          ],
          "productUrl": "https://demo.velou.com/products/texas-rose-plus?variant=37897423290565",
          "promoPrice": {
            "min": 0,
            "max": 0
          },
          "price": {
            "min": 139.95,
            "max": 139.95
          },
          "initialPrice": {
            "min": 186.95,
            "max": 186.95
          }
        }
      }
    }  

  ],
  "facets": [
    {
      "key": "price",
      "name": "Price",
      "values": [
        {
          "key": "r10",
          "count": 1,
          "lb": 80,
          "ub": 100
        },
        {
          "key": "r11",
          "count": 1,
          "lb": 100,
          "ub": 120
        },
        {
          "key": "r12",
          "count": 2,
          "lb": 120,
          "ub": 140
        }
      ]
    },
    {
      "key": "fit",
      "name": "Fit",
      "values": [
        {
          "key": "plus",
          "name": "Plus",
          "count": 2
        }
      ]
    }
  ],
  "spellSuggestions": [],
  "query": "red long sleeve dress",
  "collection": "new-arrivals"
}

Search Request

GET /search

Required API Key: search

Parameter Type Description
query String Search term used for filtering. At least one of query or collection parameters must be supplied.

Example: red long sleeve dress.

collection String Collection handle used for filtering. At least one of query or collection parameters must be supplied.

Example: dresses

from Number Pagination offset

Example: 100
Default: 0

pageSize Number Number of records per page

Example: 50
Default: 30

userId String Unique identifier for current shopper. This information is used to identify returning shoppers for personalization

Example: 51w0orqu5
Default: NULL

sessionId String Unique identifier for current session. This information is used for personalization

Example: bd0fl9aoc
Default: NULL

preprod Boolean Set true to indicate that we are running on the pre production mode. In the pre production mode, Velou receives search queries when the shoppers perform searches. But they still see the results from the website's existing search solution. Pre-production mode is usually used to examin production traffic just before deploying Velou search on production

Example: true
Default: false

returnFacets Boolean Set true to return facets

Example: true
Default: false

facets String Current selected facets as key-value pairs separated by commas

Example: color:red,sleeve_length:long
Default: NULL

campaignProducts String Comma separated value of product ids. Used with campaign value in sortBy

Example: 261252712,373849939,473673552
Default: NULL

sortBy String Sort parameter. Following values are supported at the moment.
  • rating: Sort by the star rating of the product. If the ratings summary is available, star rating is normalized using Wilson formula
  • new: Sort by product arrival timestamp in descending order
  • newc: Product arrival timestamp is divided by an integer n to create n day blocks. n is pre configured per store basis. Sorted by the resulting value in descending order.
  • newc2: The difference between product's arrival timestamp and the current timestamp is divided by an integer n. n is pre configured value. Sorting is done by the resulting value in ascending order
  • purchase: Sort by product purchase count in descending order
  • pricea: Sort by product price in ascending order
  • priced: Sort by product price in descending order
  • namea: Sort by product name in ascending order
  • named: Sort by product name in descending order
  • stocka: Sort by stock count in ascending order (Note: Stock count must be available via the index API)
  • stockd: Sort by stock count in descending order (Stock count must be available via the index API)
  • campaign: Product ids sent through campaignProducts parameter are moved to the top of the search results list. This mechanism can be used to boost arbitrary products up the search results for various marketing campaigns
  • rating2: Sort by the star rating of the product. Average star rating is normalized using Bayesian Estimate
  • vendor_based_newness: Same as newc2, The difference between product's arrival timestamp and the current timestamp is divided by a pre configured value. Sorting is done by the resulting value in ascending order. However, pre-configured number of products from each vendor is moved to the top of the list randomly. This results in each vendor having fair chance to show their products at the top of the list if there are newly arrived products from multiple vendors

Example: rating
Default: NULL

Additional supported parameters (optional): currency (3 uppercase letters, e.g. USD), country (2 uppercase letters, e.g. US), region and language (≤12 chars) — used for currency conversion and localized results when configured for your store. noSpellCheck (Boolean) disables spell correction for the request.

Search Response

Parameter Type Description
totalProductCount Number Total search results count
products Array[Product] Paginated list of search results
fallback Boolean Indicates if the search engine decided to run a fallback query instead of the query sent through the query parameter. This might happen if the original query is not producing any results. This flag can be used to display a message to the shopper indicating produced results are not for his original query
facets Array[Facet] Dynamic list of facet options to narrow down current search results
spellSuggestions Array[String] List of spell suggestions for current search term
query String Search term used for filtering if available
collection String Collection handle used for filtering if available

Search Response: Product Object

Parameter Type Description
id String Unique Velou product identifier
productId String Unique store product identifier
url String URL of original product detail page
name String Name of the product
designer String Brand name of the manufacturer
price Object Price range considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
promoPrice Object Promotional price range considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
initialPrice Object Initial price range considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
customUserData Object Custom data passed to frontend for customer specific actions like showing various badges on the products, setting customer specific ids
  • key: String
  • value: Array of strings
productPopularity Object Product ratings data. Please refer to popularity in index API for more information
defaultColorId String Id of the color variant that should be selected by default
colors Object List of color variations
ccv Object Converted price values for the product if the currency conversion is configured for this store Object

Search Response: Color Variation Object

Parameter Type Description
name String Name of the variation (Color)
swatch String URL of the swatch image if available
images Object List of images
  • key: Image size {s=small, m=medium, l=large}
  • value: Image URL
values Array[Color] Color composition of the variation if the color details are extracted
productName String Name of the color variant. Some e-commerce stores have slightly different product names for the color variations
productUrl String URL of original product detail page for this color variation
productId String Unique store product identifier for this color variation
promoPrice Object Promotional price range of the color variant considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
price Object Price range of the color variant considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
initialPrice Object Initial price range of the color variant considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
ccv Object Converted price values for the color variance if the currency conversion is configured for this store Object

Search Response: Currency Conversion Object

Parameter Type Description
price Object Converted price range of the product considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
promoPrice Object Converted promotional price range of the product considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
initialPrice Object Converted initial price range of the product considering all SKUs
  • min {Number} price lower bound
  • max {Number} price upper bound
currency String Currency code of the converted currency

Search Response: Facet Object

Parameter Type Description
key String Unique key to identify the facet
name String Name of the facet
values Array[FacetValue] List of facet values for current facet

Search Response: Facet Value Object

Parameter Type Description
key String Unique key to identify the facet value
name String Name of the facet value
count Number Number of search results for facet value

Search Response: Color Value Object

Parameter Type Description
hex String Hexadecimal value of the color
ratio Number Composition ratio of the color

Query Suggestions

Velou provides an API to return helpful query recommendations based on shopper's current search query. This API can be handy to implement an autocomplete/typeahead feature as shopper inputs a partial search query. Velou's search algorithm generates query suggestions based on your indexed products catalog as well as using previous/popular search queries.

Sample Request

curl -X GET 'https://{API_HOST}/1.0/suggestions?query=bl' \
  -H 'X-Velou-API-Key: <api-key-search>'

Sample Response

{
  "query": "bl",
  "suggestions": [
    {
      "id": 1,
      "label": "Black",
      "count": 86
    },
    {
      "id": 2,
      "label": "Black Clothing",
      "count": 75
    },
    {
      "id": 3,
      "label": "Blouse",
      "count": 40
    }
  ],
  "designers": [
    {
      "id": 1,
      "label": "Blumarine",
      "count": 12
    }
  ]
}

Suggestions Request

GET /suggestions

Required API Key: search

Parameter Type Description Default Example
query String Search term NULL bl
language String Language preference for localized suggestions, when configured for your store NULL en-gb
region String Geographical region for localized suggestions, when configured for your store NULL uk
preprod Boolean Set true to indicate that we are running on the pre production mode. In the pre production mode, Velou receives search queries when the shoppers perform searches. But they still see the results from the website's existing search solution. Pre-production mode is usually used to examin production traffic just before deploying Velou search on production false true

Suggestions Response

Parameter Type Description
suggestions Array[Suggestion] List of query suggestions matching search term
designers Array[Suggestion] List of brand suggestions matching search term
query String Search term

Suggestions Response: Suggestion Object

Parameter Type Description
id String Search term id
label String Suggested search term
count Number Number of search results for suggested search term

Similarity

Velou provides you an API to find similar products for any given product. This facility can be used to show other similar products in a product description page for your shoppers further increasing the chance of them buying a product.

Sample Request

curl --request GET \
  --url 'https://{API_HOST}/1.0/similarity?from=0&pageSize=20&productId=73529573021&variantId=12532'

Sample Response

{
  "totalProductCount": 20,
  "products": [
    {
      "product": {
        "id": "615498f5d3c391de972a22bd",
        "productId": "62853527846",
        "url": "https://demo.velou.com/products/chiffon-wrap-top",
        "name": "Navy Ruched Chiffon Wrap Top",
        "designer": "ELF",
        "price": {
          "min": 9.99,
          "max": 9.99,
          "first": 9.99
        },
        "promoPrice": {
          "min": 0,
          "max": 0,
          "first": 0
        },
        "initialPrice": {
          "min": 24.99,
          "max": 24.99,
          "first": 24.99
        },
        "customUserData": {
          "auroraId1": [
            "286504"
          ]
        },
        "defaultColorId": "1",
        "colors": {
          "1": {
            "name": "Navy",
            "swatch": "https://demo.velou.com/images/navy",
            "images": [
              {
                "s": "https://demo.velou.com/images/62853527846_s",
                "m": "https://demo.velou.com/images/62853527846_m",
                "l": "https://demo.velou.com/images/62853527846_l"
              }
            ],
            "promoPrice": {
              "min": 0,
              "max": 0
            },
            "price": {
              "min": 9.99,
              "max": 9.99,
              "first": 9.99
            },
            "initialPrice": {
              "min": 24.99,
              "max": 24.99,
              "first": 24.99
            }
          }
        }
      }
    },
    ...
  ],
  "facets": [
    {
      "key": "sizes",
      "name": "Size",
      "values": [
        {
          "key": "6",
          "name": "6",
          "count": 6
        },
        {
          "key": "8",
          "name": "8",
          "count": 9
        },
        {
          "key": "10",
          "name": "10",
          "count": 9
        },
        {
          "key": "12",
          "name": "12",
          "count": 10
        },
        {
          "key": "14",
          "name": "14",
          "count": 6
        },
        {
          "key": "16",
          "name": "16",
          "count": 5
        },
        {
          "key": "18",
          "name": "18",
          "count": 1
        },
        {
          "key": "s",
          "name": "S",
          "count": 6
        },
        {
          "key": "m",
          "name": "M",
          "count": 6
        },
        {
          "key": "l",
          "name": "L",
          "count": 5
        }
      ],
      "specialValues": []
    }
  ],
  "sourceProduct": {
    "productId": "73529573021",
    "image": "https://demo.velou.com/images/00100029021_XM?$plptest$&fmt=webp",
    "name": "Blue Knitted Wrap Jumper"
  }
}

Similarity Request

GET /similarity

Required API Key: search

Parameter Type Description Default Example
productId String Velou search engine will find the similar products for the product that has this id. Required. Alphanumeric and underscores only (1–200 chars). NULL 628373838
from Number Pagination offset 0 100
pageSize Number Number of records per page 10 50
variantId String Variant id. When searching similar products, this variant will also be considered if available. Alphanumeric, underscores and dashes only (1–100 chars). NULL 62524
facets String Current selected facets as key-value pairs separated by commas NULL sizes:10,sleeve_length:long
sortBy String Sort order. One of similarity, new, pricea, priced NULL pricea
currency String Currency code (3 uppercase letters) for currency conversion if configured NULL USD
country String Country code (2 uppercase letters) NULL US

Similarity Response

Parameter Type Description
totalProductCount Number Total similar items count
products Array[ProductWrapper] Paginated list of similar items
facets Array[Facet] Dynamic list of facet options to narrow down similar items list
sourceProduct Object Details about the product similar items are returned for.
  • productId: {String} Unique store product identifier
  • image: {URL} main image of the product
  • name: {String} Name of the product

Response: ProductWrapper Object

Parameter Type Description
product Array[Product] Product Object

Complete The Look

The Complete the Look API enables customers to discover complementary products for a specific item, enhancing the shopping experience. By providing a curated set of products based on a given product ID, the API allows retailers to offer tailored outfit recommendations, encouraging shoppers to visualize and purchase a complete look.

Sample request

curl 'https://demo.velou.com/ctl?productId=DBGS123N'

Sample response

{
    "ctlProducts": [
        [
            {
                "id": "615498f5d3c391de972a22bd",
                "productId": "DBGS123N",
                "url": "https://demo.velou.com/62853527846/pull-over-hoodie-DBGS123N",
                "name": "Pull Over Hoodie",
                "designer": "Brand",
                "price": {
                    "min": 19.99,
                    "max": 19.99,
                    "first": 19.99
                },
                "promoPrice": {
                    "min": 0,
                    "max": 0,
                    "first": 0
                },
                "initialPrice": {
                    "min": 39.99,
                    "max": 39.99,
                    "first": 39.99
                },
                "customUserData": {
                    "bannerInformation1": [
                        "none",
                        "n",
                        "80",
                        "Yes"
                    ],
                    "dropShipProduct1": [
                        "NO"
                    ],
                    "promotion1": [
                        "No"
                    ],
                    "auroraId1": [
                        "12345"
                    ]
                },
                "defaultColorId": "1",
                "colors": {
                    "1": {
                        "name": "Red",
                        "swatch": "https://www.example.com/swatch-red.jpg",
                        "images": [
                            {
                                "s": "https://www.example.com/image-small-red.jpg",
                                "m": "https://www.example.com/image-medium-red.jpg",
                                "l": "https://www.example.com/image-large-red.jpg"
                            }
                        ],
                        "values": [],
                        "productName": "",
                        "promoPrice": {
                            "min": 0,
                            "max": 0
                        },
                        "price": {
                            "min": 19.99,
                            "max": 19.99,
                            "first": 19.99
                        },
                        "initialPrice": {
                            "min": 39.99,
                            "max": 39.99,
                            "first": 39.99
                        }
                    }
                },
                "gender": "Unisex"
            },
            {
                "id": "615498f5d3c391de972a22bc",
                 ------
            },
            {
                "id": "615498f5d3c391de972a22br",
                 ------
            },
            {
                "id": "615498f5d3c391de972a22bj",
                 ------
            }
        ]
    ]
}

Complete The Look Request

GET /ctl

Parameter Type Description Example
productId String The product ID is used to retrieve the CTL product set DBGS123N

Complete The Look Response

Parameter Type Description
ctlProducts Array [Array[Product]] A list of product sets that is curated for complete the look

Analytics

Event Tracking

Velou uses event tracking on your store to generate valuable insights on your shopper behavior and to monitor how Velou contributes to the convertion of your customers. Velou also uses these data points to boost the most important products to the top of search results based on past shopper behavior (ranking). It is highly recommend you report all event types accurately to get the maximum benefit through Velou's reporting platform and ranking algorithm.

Sample Request

curl -X POST 'https://{API_HOST}/1.0/tracking' \
  -H 'Content-Type: application/json' \
  -d '
  {
    "type": "Search",
    "data": {
      "query": "Red Shirt",
      "pageSize": 30,
      "sortBy": "relevance",
      "productIds": [
        "6153342714048",
        "6642820382912",
        "6536276934848"
      ],
      "facets": [
        {
          "key": "pattern",
          "value": "floral"
        }
      ],
      "totalProducts": 3
    },
    "sessionId": "it2qa7ksj",
    "userId": "bi34ly82v",
    "storeId": "storeId"
  }'

Sample Response

{
  "ok":true
}

Request

POST /tracking

Required API Key: analytics

Parameter Type Description
type Enum ["SiteView", "Search", "PageChange", "SortByChange", "ProductClick","PromotionClick", "AddToCart", "OrderComplete", "Purchase", "ViewSimilarProducts", "SimilarProductClick", "CTLLoad", "CTLViewLookClick", "CTLProductClick", "CTLPopupProductClick", "CTLPageChange", "CTLPopupPageChange"] Type of activity performed by the shopper
data Object Additional important details related to the event.

Depending on the type, the values contained in data will be different:
type = SiteView:
  • location {String} The current page address
  • referrer {String} The URI of the page that linked to this page
  • userAgent {String} The user-agent header
  • region {String} Geographical region where the site view is recorded
  • language {String} Language preference of the user
  • currency {String} Monetary unit used in the site view
type = Search:
  • query {String} Search term
  • productIds {Array[String]} List of product IDs returned for search query
  • pageSize {Number} Number of items to appear on search results page
  • sortBy {String} Selected sortBy option for search query
  • totalProducts {Number} Total number of records returned for search query
  • facets {Array[Facet]} List of selected facets
  • region {String} Geographical region where the search is conducted
  • language {String} Language preference of the user
  • currency {String} Monetary unit used in the presented prices
type = PageChange:
  • query {String} Search term
  • productIds {Array[String]} List of product IDs returned for search query
  • facets {Array[Facet]} List of selected facets
  • pageSize {Number} Number of items to appear on search results page
  • sortBy {String} Selected sortBy option for search query
  • page {Number} Current page number
  • region {String} Geographical region where the search is conducted
  • language {String} Language preference of the user
  • currency {String} Monetary unit used in the presented prices
type = ProductClick:
  • query {String} Search term
  • productIds {Array[String]} List of product IDs returned for search query
  • facets {Array[Facet]} List of selected facets
  • pageSize {Number} Number of items to appear on search results page
  • sortBy {String} Selected sortBy option for search query
  • page {Number} Current page number
  • clickProductId {String} The clicked product id
  • region {String} Geographical region where the search is conducted
  • language {String} Language preference of the user
  • currency {String} Monetary unit used in the presented prices
type = PromotionClick:
  • query {String} Search term
  • productIds {Array[String]} List of product IDs returned for search query
  • facets {Array[Facet]} List of selected facets
  • promotions {Array[String]} List of promotion IDs returned for search query
  • pageSize {Number} Number of items to appear on search results page
  • sortBy {String} Selected sortBy option for search query
  • page {Number} Current page number
  • clickPromotionId {String} The clicked promotion id
  • region {String} Geographical region where the search is conducted
  • language {String} Language preference of the user
  • currency {String} Monetary unit used in the presented prices
type = SortByChange:
  • query {String} Search term
  • productIds {Array[String]} List of product IDs returned for search query
  • facets {Array[Facet]} List of selected facets
  • pageSize {Number} Number of items to appear on search results p>age
  • sortBy {String} Selected sortBy option for search query
  • region {String} Geographical region where the search is conducted
  • language {String} Language preference of the user
  • currency {String} Monetary unit used in the presented prices
type = AddToCart:
  • query {String} Search term
  • productIds {Array[String]} List of product IDs returned for search query
  • facets {Array[Facet]} List of selected facets
  • pageSize {Number} Number of items to appear on search results page
  • sortBy {String} Selected sortBy option for search query
  • page {Number} Current page number
  • totalProducts {Number} The total number of products.
  • addProductId {String} The product Id added to cart.
  • qty {Number} The product quantity added to cart.
  • region {String} Geographical region where the search is conducted
  • language {String} Language preference of the user
  • currency {String} Monetary unit used in the presented prices
type = OrderComplete:
  • orderId {String} Unique order identifier
  • products {Array[Product]} List of products order completed by the shopper
type = Purchase:
  • orderId {String} Unique order identifier
  • products {Array[Product]} List of products purchased by the shopper
type = ViewSimilarProducts:
  • productId {String} The original product id which used to view other similar products.
type = SimilarProductClick:
  • similarProductId {String} The similar product id.
  • clickProductId {String} The clicked product id.
Related Products
    type = CTLLoad:
    • query {String} Search term
    • productIds {Array[String]} List of product IDs returned for search query
    • facets {Array[Facet]} List of selected facets
    • pageSize {Number} Number of items to appear on search results page
    • sortBy {String} Selected sortBy option for search query
    • region {String} Geographical region where the search is conducted
    • language {String} Language preference of the user
    • currency {String} Monetary unit used in the presented prices
    • baseProductId {String} The selected Product id
    • relatedProducts {Array[String]} List of CTL products for current product
    • totalProducts {Number} Number of total products returned for search query
    type = CTLViewLookClick:
    • query {String} Search term
    • productIds {Array[String]} List of product IDs returned for search query
    • facets {Array[Facet]} List of selected facets
    • pageSize {Number} Number of items to appear on search results page
    • sortBy {String} Selected sortBy option for search query
    • region {String} Geographical region where the search is conducted
    • language {String} Language preference of the user
    • currency {String} Monetary unit used in the presented prices
    • baseProductId {String} The selected Product id
    • relatedProducts {Array[String]} List of CTL products for current product
    • totalProducts {Number} Number of total products returned for search query
    • position {Number} Current position(from 1 to 9) of clicked View Look button
    type = CTLProductClick:
    • query {String} Search term
    • productIds {Array[String]} List of product IDs returned for search query
    • facets {Array[Facet]} List of selected facets
    • pageSize {Number} Number of items to appear on search results page
    • sortBy {String} Selected sortBy option for search query
    • region {String} Geographical region where the search is conducted
    • language {String} Language preference of the user
    • currency {String} Monetary unit used in the presented prices
    • baseProductId {String} The selected Product id
    • relatedProducts {Array[String]} List of CTL products for current product
    • totalProducts {Number} Number of total products returned for search query
    • selectedProduct {Array[String]} Product details of user clicks on a product that shows in the CTL carousel
      • productId {String} Clicked Product id in CTL carousel
      • position {Number} Position of clicked product in CTL carousel
      • internalCategory {String} Internal category of clicked product in CTL carousel
    type = CTLPopupProductClick:
    • query {String} Search term
    • productIds {Array[String]} List of product IDs returned for search query
    • facets {Array[Facet]} List of selected facets
    • pageSize {Number} Number of items to appear on search results page
    • sortBy {String} Selected sortBy option for search query
    • region {String} Geographical region where the search is conducted
    • language {String} Language preference of the user
    • currency {String} Monetary unit used in the presented prices
    • baseProductId {String} The selected Product id
    • relatedProducts {Array[String]} List of CTL products for current product
    • totalProducts {Number} Number of total products returned for search query
    • selectedProduct {Array[String]} Product details of user clicks on a product that shows in the CTL popup
      • productId {String} Clicked Product id in popup
      • position {Number} Position of clicked product in popup
      • internalCategory {String} Internal category of clicked product in popup
    type = CTLPageChange:
    • query {String} Search term
    • productIds {Array[String]} List of product IDs returned for search query
    • facets {Array[Facet]} List of selected facets
    • pageSize {Number} Number of items to appear on search results page
    • sortBy {String} Selected sortBy option for search query
    • region {String} Geographical region where the search is conducted
    • language {String} Language preference of the user
    • currency {String} Monetary unit used in the presented prices
    • baseProductId {String} The selected Product id
    • relatedProducts {Array[String]} List of CTL products for current product
    • totalProducts {Number} Number of total products returned for search query
    • pageTo {Number} Move from this page number in CTL carousel
    • pageFrom {Number} Move into this page number in CTL carousel
    type=CTLPopupPageChange:
    • query {String} Search term
    • productIds {Array[String]} List of product IDs returned for search query
    • facets {Array[Facet]} List of selected facets
    • pageSize {Number} Number of items to appear on search results page
    • sortBy {String} Selected sortBy option for search query
    • region {String} Geographical region where the search is conducted
    • language {String} Language preference of the user
    • currency {String} Monetary unit used in the presented prices
    • baseProductId {String} The selected Product id
    • relatedProducts {Array[String]} List of CTL products for current product
    • totalProducts {Number} Number of total products returned for search query
    • pageTo {Number} Move from this page number in popup
    • pageFrom {Number} Move into this page number in popup
userId String Randomly generated, anonymous string using base-36 encoding, designed for user tracking without storing any Personally Identifiable Information (PII)
sessionId String Randomly generated, anonymous string using base-36 encoding, designed for session tracking without storing any Personally Identifiable Information (PII)
storeId String Unique identifier of the shop

Request: Purchased Product Object

Parameter Type Description
id String Unique product identifier
price Number Price of the product
qty Number Quantity of the product

Response

Parameter Type Description
result Enum ["success", "error"] Result of the request

Error Handling

Whether a request succeeded is indicated by the HTTP status code. A 2xx status code indicates success, whereas a 4xx or 5xx status code indicates failure.

When a request fails, the response body is still JSON and always contains a message field describing the error, which you can inspect for debugging.

The Velou API uses the following error codes:

Error Code Meaning
401 Unauthorized – Your API Key is missing or invalid. Rejected at the API gateway.
403 Forbidden – Your API Key is valid but does not have permission for this resource (e.g. an admin-only endpoint called with a non-admin key).
404 Not Found – Your request is looking for a non-existent resource.
409 Validation Error – The request failed schema validation. The response body lists each failed constraint (see below).
500 Internal Server Error – An unexpected error occurred server-side. Retry after a few minutes or contact Velou if the problem persists.
{
  "success": false,
  "code": "InvalidArgument",
  "errors": [
    {
      "instancePath": "/fieldName",
      "keyword": "errorMessage",
      "params": { "errors": [ { "keyword": "minLength" } ] },
      "message": "Human-readable description of the failed constraint"
    }
  ],
  "message": "Validation failure"
}

Gateway-level auth errors (401/403) use a simpler shape, { "message": "..." }, since they are produced before the request reaches the service.

Content Generation Webhook

In addition to the search functionality, Velou can enrich your data by providing you product features identified by Velou. You can use webhook subscriptions to receive this information. Once subscribed, content generation webhooks will be called as soon as Velou identify the features of any product you send via the indexing API. It is possible to call the webhooks multiple times for a single product as Velou identify features at various stages of the analysis process. (E.g. Text analysis, Image analysis, etc)

Webhook Headers

Header Description Example
x-velou-topic Webhook Topic tags
x-velou-hmac-sha256 base64 encoded string that is used to verify a webhook notification BE90+RWqMIFylcyc969HlGznlZ9MPnGQxvmEs+o5C7U=
x-velou-store-id Id of the store registered with Velou my_store_123
x-velou-ts UNIX timestamp in milliseconds. This is used to compute the HMAC hash for request authentication 1638164106697
x-velou-api-version Version of the webhook API being used. 1.3
x-velou-webhook-id Id of the webhook 526143728

Webhook Body

Parameter Type Description Default
id String Unique Velou product identifier
productId String Unique store product identifier
category String Category of the product
attributes Object Object containing key product attributes and their associated values
  • displayName: {Object} Localized display name
  • attributesValues: {Array} Array of possible values for the attribute
  • synonyms: {Array} Array of synonyms for the attribute value
  • trending: {Boolean} Indicates if the value is trending
productVersion Number Version number of the product, indicating updates or changes to the product data
generatedContent Array Array containing generated contents using AI(i.e. Title, Description etc.)
  • fieldName: {String} name of the generated content
  • values: {Object} locale-based content

Example webhook body given below

{
  "id": "5f637c246b9eeecb1134a212",
  "productId": "812456103",
  "category": "dresses",
  "attributes": {
    "gender": {
      "displayName": {
        "en-gb": "Gender",
        "fr-fr": "Genre"
      },
      "attributesValues": [
        {
          "women": {
            "displayName": {
              "en-gb": "Women",
              "fr-fr": "Femmes"
            },
            "synonyms": [
              {
                "ladies": {
                  "displayName": {
                    "en-gb": "Ladies",
                    "fr-fr": "Dames"
                  }
                }
              }
            ],
            "trending": true
          }
        }
      ]
    },
    "color": {
      "displayName": {
        "en-gb": "Color",
        "fr-fr": "Couleur"
      },
      "attributesValues": [
        {
          "black": {
            "displayName": {
              "en-gb": "Black",
              "fr-fr": "Noir"
            },
            "synonyms": []
          }
        }
      ]
    },
    "pattern": {
      "displayName": {
        "en-gb": "Pattern",
        "fr-fr": "Motif"
      },
      "attributesValues": [
        {
          "solid": {
            "displayName": {
              "en-gb": "Solid",
              "fr-fr": "Uni"
            },
            "synonyms": [
              {
                "plain": {
                  "displayName": {
                    "en-gb": "Plain",
                    "fr-fr": "Simple"
                  }
                }
              },
              {
                "without_pattern": {
                  "displayName": {
                    "en-gb": "Without pattern",
                    "fr-fr": "Sans motif"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  },
  "productVersion": 34,
  "generatedContent": [
    {
      "fieldName": "productDescription",
      "values": {
        "en-gb": "This elegant black bodycon dress is perfect for evening events and special occasions. Featuring a solid pattern and a flattering fit, the dress includes a mini length, plunging neckline, ruching details, and long sleeves. Designed with a tulip hemline, this piece combines sophistication with style.",
        "fr-fr": "Cette élégante robe moulante noire est parfaite pour les événements du soir et les occasions spéciales. Avec un motif uni et une coupe flatteuse, la robe comprend une longueur mini, un décolleté plongeant, des détails froncés et des manches longues. Conçue avec un ourlet en forme de tulipe, cette pièce combine sophistication et style."
      }
    },
    {
      "fieldName": "productTitle",
      "values": {
        "en-gb": "Women's Solid Black Bodycon Dress",
        "fr-fr": "Robe moulante noire unie pour femme"
      }
    }
  ]
}

Retry Logic

If the webhook is not responded within 5 seconds or any status code other than 2xx is received, Velou consider it as a failure and fall back to a retry cycle. Following retry strategy is currently in place

  1. Try 3 times with 30 second interval in between
  2. Try 3 times with 2 minutes wait time between each attempt
  3. Try 3 times with 5 minutes wait time between each attempt
  4. Try 3 times with 1 hour wait time between each attempt
  5. Try 2 times with 6 hour wait time between each attempt
  6. Try one last time after 24 hours

Webhook Authentication

When you receive a webhook request, it is very important to verify that the request has originated from Velou before processing it any further. Velou provides a digital signature for you to use in this verification process. A string is generated by concatenating body of the request with number of other parameters. Final signature is obtained by signing this string with a shared secret key. Velou provides you this secret key as part of the setup process. A simple nodejs snippet is given below in order to explain the authentication process.

const express = require('express')
const crypto = require('crypto')
const getRawBody = require('raw-body')
const app = express()

const webhookSecret = MY_VELOU_SECRET

app.post('/webhook', async (req, res) => {

  try {
    // Parse the request body
    const body = await getRawBody(req)

    // Extract x-velou-hmac-sha256 header from the request
    const hmacHash = req.header('x-velou-hmac-sha256')

    // Extract x-velou-store-id header from the request
    const storeId = req.header('x-velou-store-id')

    // Extract x-velou-ts header from the request. 
    // This is a UNIX timestamp in milliseconds indicating the request created time.
    const signatureTs = req.header('x-velou-ts')

    // Extract x-velou-topic header from the request
    // This is the webhooks topic. For tag generation, its value is "tags"
    const topic = req.header('x-velou-topic')

    // Extract x-velou-webhook-id header from the request
    // When a webhook is registered with velou, its given a unique id
    const id = req.header('x-velou-webhook-id')

    const signatureSourceComponents = [
      storeId, signatureTs, topic, id, body.toString('utf8')
    ]

    const computedHash = crypto.createHmac('sha256', webhookSecret)
      .update(signatureSourceComponents.join('.'))
      .digest('base64')

    if (computedHash === hmacHash) {
      console.log("Webhook source confirmed. Continue processing");
      res.sendStatus(200)
    } else {
      console.log("Unidentified webhook source. Do not process");
      res.sendStatus(403)
    }
  } catch (e) {
    console.error(e)
    res.sendStatus(500)
  }
})

app.listen(43215)

Best Practices

JavaScript Integration

To integrate the Velou functions from the front end, Velou will provide a customized JavaScript implementation that needs to be embedded in the HTML header of the application as shown in the example. Velou will manage the search look-and-feel of the functions as agreed with both parties.

<html>
<head>
    <script src="https://{VELOU_JS_HOST}/velou.min.js"></script>
</head>
</html>

Search Integration

A route/page as shown in the example will include the relevant headers and footers. The page should also include a div with a unique id (i.e. velou-search-results) to embed the search results.

https://{YOUR_DOMAIN}/search-results