Level 1: SVK Primitives

Prism API Reference

Personalized product search service that wraps Shopkeep with user-aware reranking and filtering. Use Prism for user-specific product discovery tailored to individual taste profiles.

When to Use Prism

  • • User-specific product recommendations
  • • Personalized discovery feeds
  • • Multi-modal searches with user history
  • • Brand/domain scoped personalized search

API Configuration

Base URL: https://api-prism.bestomer.io/

Authentication: HTTP Bearer token

Authorization: Bearer $PRISM_TOKEN

Core Endpoint: Unified Search

POST /search/unified is the primary endpoint for Prism. It accepts a flexible mix of capture references, text queries, product handles, and image URLs in a single request.

Request Parameters

{
  // REQUIRED
  "queries": [
    { "query": "text search" },
    { "image_url": "https://..." },
    { "product_variant_handle": "https://..." },
    { "user_id": "uuid", "capture_id": "uuid" }
  ],
  "n_products": 30,
  "n_pool": 300,
  "noise": 0.0,

  // PERSONALIZATION (optional)
  "user_id": "user-uuid",
  "search_weight": 0.5,
  "personalization_weight": 0.5,

  // ADVANCED (optional)
  "domains": ["cb2.com", "westelm.com"],
  "window_id": "window-uuid",
  "include_visualization": false
}

Response Structure

{
  "results": [
    {
      "maxsim_sim": 0.87,
      "product_handle": "https://...",
      "product": {
        "name": "Product Name",
        "brand": "Brand",
        "images": ["https://..."],
        "offers": [{
          "price": 49.99,
          "currency": "USD",
          "availability": "in_stock"
        }],
        "_prism_metadata": {
          "personalization_applied": true,
          "search_score": 0.85,
          "personalization_score": 0.94,
          "final_score": 0.895
        }
      }
    }
  ],
  "personalization_applied": true,
  "total_signals_count": 57,
  "impactful_signals_count": 23,
  "processing_time_ms": 156.3
}

TypeScript Example

async function searchUnified(params: {
  queries: Array<
    | { query: string }
    | { image_url: string }
    | { product_variant_handle: string }
    | { user_id: string; capture_id: string }
  >;
  n_products: number;
  n_pool: number;
  noise: number;
  user_id?: string;
  search_weight?: number;
  personalization_weight?: number;
}) {
  const response = await fetch('https://api-prism.bestomer.io/search/unified', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.PRISM_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(params),
  });

  return await response.json();
}

// Example: Multi-modal search
const results = await searchUnified({
  queries: [
    { query: "coastal grandmother aesthetic" },
    { product_variant_handle: "https://cb2.com/products/linen-pillow" },
    { user_id: "user-123", capture_id: "cap-456" }
  ],
  n_products: 30,
  n_pool: 300,
  noise: 0.0,
  user_id: "user-123",
  search_weight: 0.5,
  personalization_weight: 0.5
});

Common Patterns

Pattern 1: Multi-Modal Search

Combine text, images, and products in one search:

const results = await searchUnified({
  queries: [
    { query: "scandinavian dining room" },
    { user_id: userId, capture_id: inspoCapture1 },
    { user_id: userId, capture_id: inspoCapture2 },
    { product_variant_handle: "https://cb2.com/products/dining-table" }
  ],
  n_products: 50,
  n_pool: 500,
  noise: 0.05,
  user_id: userId,
  search_weight: 0.4,
  personalization_weight: 0.6
});

Pattern 2: Domain-Specific Exploration

Explore products within favorite stores:

const results = await searchUnified({
  queries: [{ query: "throw pillows" }],
  n_products: 30,
  n_pool: 300,
  noise: 0.0,
  user_id: userId,
  domains: ["cb2.com", "westelm.com", "anthropologie.com"],
  search_weight: 0.5,
  personalization_weight: 0.5
});

Other Endpoints

Brand Search: POST /search/brand

Search within specific brand catalogs with personalization:

{
  "queries": [{ "query": "minimal leather bags" }],
  "n_products": 30,
  "n_pool": 300,
  "noise": 0.0,
  "user_id": "user-123",
  "brands": ["Everlane", "Patagonia", "Allbirds"]
}

Domain Search: POST /search/domain

Search within specific retailer domains:

{
  "queries": [{ "query": "dining chairs" }],
  "n_products": 30,
  "n_pool": 300,
  "noise": 0.0,
  "user_id": "user-123",
  "domains": ["cb2.com", "westelm.com"]
}

Troubleshooting

Issue: No Personalization Applied

Cause: User has insufficient sentiment history

if (!response.personalization_applied) {
  console.log("User needs more sentiment signals");
  console.log("Total signals:", response.total_signals_count);
  console.log("Impactful signals:", response.impactful_signals_count);
}

Solution: Prompt user to like/dislike products or upload captures

Issue: Over-Personalization (Filter Bubble)

Solution: Reduce personalization weight and add noise

const results = await searchUnified({
  queries: [{ query: query }],
  n_products: 50,
  n_pool: 500,
  noise: 0.15,              // Add diversity
  user_id: userId,
  search_weight: 0.7,       // Increase search weight
  personalization_weight: 0.3  // Decrease personalization
});

Related Resources