Skip to content

Uniqueness

VibeIQ allows users to configure custom uniqueness requirements at the type property level. These constraints ensure that certain property values remain unique according to user-defined settings.

Uniqueness constraints are commonly used for properties like SKU numbers, product codes, style numbers, or other identifiers where duplicate values would cause conflicts or data integrity issues.

Types of Uniqueness

Globally Unique Properties

When a property is marked as globally unique, VibeIQ ensures that the value for this property is never duplicated across any existing records in that type hierarchy.

Scope

  • The uniqueness constraint applies across the entire type hierarchy
  • For example, if sku is globally unique for item, the value must be unique across item, item:footwear, item:apparel, and all other item types
  • A given value can only be used once across all entities of that type
  • You can turn off uniqueness for a subtype

Enforcement

When you create or update an entity with a globally unique property:

  1. The system checks if the property value already exists for any other entity in the type hierarchy
  2. If it exists, the create/update operation is blocked
  3. If it doesn't exist, the operation proceeds

Supported Entity Types

Currently, uniqueness constraints can be applied to:

  • Items
  • Project Items

Family-Level Uniqueness

When a property is marked as unique within a family, VibeIQ enforces uniqueness only within that specific family.

Scope

  • The value can be reused across different families
  • Duplicate values within the same family are not allowed
  • This applies to Items and Project Items that support family-level organization

Example

If colorCode is marked as family-unique:

  • Family A can have an option with colorCode: "RED-01"
  • Family B can also have an option with colorCode: "RED-01"
  • Within Family A, no two options can share the same colorCode value

What the check applies to

  • The family-uniqueness check runs only on Option items. Family items are not validated against this constraint, since family-uniqueness describes the relationship between options under a shared family.
  • optionName is always treated as family-unique by default, even if the flag is not explicitly set on the property — no two options under the same family can share the same optionName.
  • String values are compared case-insensitively (the service uppercases both sides before comparing), so "RED-01" and "red-01" are considered duplicates.
  • Empty values (null, undefined, or whitespace-only strings) are skipped — they do not count as duplicates of each other.

No backfill required for family-level uniqueness

Family-level uniqueness is enforced automatically by the backend on every create and update — there is no separate registry to populate, so you do not need to run the backfill endpoint when enabling this constraint. The check happens at write time against the current family's other options.

Existing duplicate values within a family are not retroactively detected on enable; they will be flagged the next time one of the conflicting options is updated. If you need to find existing duplicates ahead of time, run a one-off query against the family's options.

How to Configure Uniqueness

Uniqueness is configured at the type property level through the Admin Console:

  1. Navigate to Type Configuration in the Admin Console
  2. Select the type you want to configure (e.g., item:footwear)
  3. Open the property you want to make unique
  4. In the Uniqueness section, choose one of the following:
  5. Globally unique - The property value is unique across all items
  6. Unique in family - The property value is unique for an item family

Configuration UI

When editing a type property, you'll see the Uniqueness section with two toggle options:

  • ☑️ Globally unique? The property value is unique across all items.
  • Unique in family? The property value is unique for an item family.

These options are mutually exclusive - you can enable one or neither, but not both.

Important Limits

  • Only 10 properties per entity can be marked as globally unique
  • This limit helps maintain performance and data integrity

Once configured, the system will automatically enforce uniqueness constraints on all create and update operations going forward.

Backfilling Uniqueness Constraints

Backfill only applies to globally unique properties

Global uniqueness is enforced against a registry of already-seen values, which has to be populated for every existing entity before the constraint can be relied on. Family-level uniqueness does not use this registry and is enforced directly by the backend at write time — no backfill is required, and the endpoint below has no effect on family-unique properties.

When you mark a property as globally unique, you need to ensure that all existing entity data complies with the uniqueness constraint. The backfill endpoint validates existing data and registers unique values.

When to Backfill

Use the backfill endpoint when:

  • A property is newly marked as globally unique and you need to validate existing data
  • You need to ensure all existing entities comply with global uniqueness constraints
  • You want to identify duplicate values that must be resolved before enforcing global uniqueness

Backfill Endpoint

POST /identities/backfill

Request Body

{
  "typePath": "item:product",
  "propertySlug": "sku"
}

Parameters

Parameter Type Required Description
typePath string Yes The type path for the entities.

Single type: "item:product" - backfills only that specific type
Type hierarchy: "item" - backfills all types in the hierarchy
propertySlug string Yes The slug of the property marked as globally unique.

The property must have isUniqueProperty: true in the type definition.

How Backfill Works

Single Type Backfill

When typePath specifies a complete type path (e.g., "item:product"):

  1. Validates that the property is marked as globally unique for that type
  2. Fetches all entities of that specific type
  3. Filters entities that have values for the specified property
  4. Checks for duplicate values within the existing entity data
  5. Checks for duplicate values against property values already registered in the system
  6. Registers globally unique property values only for entities with non-duplicate values
  7. Reports any duplicate values found so they can be resolved
Multiple Type Backfill

When typePath specifies only a root type (e.g., "item"):

  1. Retrieves the entire type hierarchy for that root
  2. Iterates through each type in the hierarchy
  3. Performs single type backfill for each type that has the property marked as globally unique
  4. Continues processing even if some types fail, returning all errors at the end
Property Level Handling

For multi-level entity types (item and project-item), the backfill respects property levels:

  • Family-level properties: Only processes entities with the family role
  • Option-level properties: Only processes entities with the option role
  • Overridable properties: Treated as family-level

Response

Success (200)

Returns when all property values have been successfully validated and registered for global uniqueness enforcement.

{}
Error (400)

Returns detailed error information if duplicate values are found or validation fails.

{
  "incomingDuplicates": {
    "message": "Duplicate property values found in incoming entities",
    "details": {
      "SKU-123": ["item-id-1", "item-id-2"],
      "SKU-456": ["item-id-3", "item-id-4"]
    }
  },
  "incomingAndExistingDuplicates": {
    "message": "Duplicate property values found in incoming + existing entities",
    "details": {
      "SKU-789": ["item-id-5", "item-id-6"]
    }
  },
  "creation": {
    "message": "Error registering globally unique values",
    "details": "..."
  }
}

Backfill Examples

Example 1: Backfill a Specific Type

Validate and register all SKU values for a single type:

curl -X POST https://api.vibeiq.com/identities/backfill \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "typePath": "item:shoe",
    "propertySlug": "sku"
  }'

This processes all entities of type item:shoe and ensures SKU values are globally unique. If duplicate SKUs are found, they will be reported in the error response.

Example 2: Backfill an Entire Type Hierarchy

Validate and register product codes across all types in a hierarchy:

curl -X POST https://api.vibeiq.com/identities/backfill \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "typePath": "item",
    "propertySlug": "productCode"
  }'

This processes all types in the item hierarchy (e.g., item, item:shoe, item:apparel) where productCode is marked as globally unique.

Error Scenarios

The backfill endpoint handles several validation scenarios:

Property Not Marked as Globally Unique

The property must have isUniqueProperty: true in the type definition. If not, a BadRequestException is thrown.

Type Not Found

If the specified typePath doesn't exist, a BadRequestException is thrown.

Duplicate Values in Entity Data

When entities share the same property value, those duplicates are reported in the error response. These duplicates must be resolved before global uniqueness can be enforced.

Duplicate Values Already Registered

Property values that have already been registered for global uniqueness enforcement are automatically skipped.

Registration Errors

Any errors that occur during the registration process are reported in the error response.

Important Considerations

Processing Behavior
  • Only entities with non-null, non-undefined, and non-empty values are processed
  • Entities whose property values are already registered are automatically skipped
  • For multi-type backfills, processing continues even if individual types fail

Authentication

The backfill endpoint follows the standard Contrail authentication patterns. Ensure your request includes proper credentials and organization ID.