Docs
    GuidesAPI ReferenceBlog
    Sign inCreate account
    Overview

    Getting started

    Sign upAPI keysQuickstartLoad your catalog

    Integration

    Tracking EventsIdentity StitchingPersonalisation

    Production

    Errors & status codesRetries & rate limitsTypeScript SDKTroubleshooting

    Reference

    API ReferenceVersioningChangelog
    HomeDocumentationPersonalisation
    Previous
    Identity Stitching
    Next
    Errors & status codes

    Skip the ML, Ship the Revenue

    Product

    • How It Works
    • Features
    • For Startups
    • For Developers

    Developers

    • Documentation

    Company

    • Blog
    • Contact

    © 2026 Lehnz, Inc. All rights reserved.

    Integration

    Recommendations

    lehnz provides five recommendation modes — all use your publishable key and can be called from the browser.

    Five modes

    ModeEndpointUse it for
    User RecommendationsPOST /recommendA personalized ranked list for a specific user.
    Item RecommendationsGET /item/:item_id"Customers also viewed" sections.
    Session RecommendationsPOST /recommend/session"Because you viewed X" rows.
    Basket RecommendationsPOST /recommend/basket"Frequently bought together" on cart pages.
    Price-OptimizedPOST /recommend/price_optimizedDrop-in for /recommend, re-ranked by price bucket.

    User recommendations

    POSThttps://recommendations.lehnz.com/recommend
    Request body
    FieldRequiredDescription
    user_idYesThe user to generate recommendations for.
    limitNoNumber of items to return (default: 12).
    pageNoPage offset for pagination (default: 1).
    placementNoContext hint — home | pdp | cart | any custom string.
    Cold start

    Users with no event history automatically receive popularity-based recommendations. Recommendation quality improves as behavioral events accumulate.

    Item recommendations

    GEThttps://recommendations.lehnz.com/item/:item_id
    Query paramDefaultDescription
    limit4Items to return
    page1Pagination offset
    modesemanticRecommendation mode

    Response shape is the same as POST /recommend.

    itemRecs.ts
    // Get items similar to a given product (for "Customers also viewed")
    const res = await fetch(
    `https://recommendations.lehnz.com/item/${product.id}?limit=4`,
    {
    headers: {
    'X-API-KEY': process.env.NEXT_PUBLIC_LEHNZ_PUBLISHABLE_KEY!,
    },
    }
    );
    const { data } = await res.json();

    Session recommendations

    POSThttps://recommendations.lehnz.com/recommend/session

    Returns items nearest to a single recently-clicked item using vector similarity search. Use on product detail pages or in "Because you viewed X" rows.

    Request body
    FieldRequiredDescription
    clicked_item_idYesThe item the user just clicked.
    limitNoItems to return (default: 10).
    pageNoPagination offset (default: 1).
    modeNoRecommendation mode (default: auto).
    filtersNoFree-form JSON filter object.
    sessionRecs.ts
    const res = await fetch('https://recommendations.lehnz.com/recommend/session', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'X-API-KEY': process.env.NEXT_PUBLIC_LEHNZ_PUBLISHABLE_KEY!,
    },
    body: JSON.stringify({ clicked_item_id: product.id, limit: 6 }),
    });

    Basket recommendations

    POSThttps://recommendations.lehnz.com/recommend/basket

    Returns items that co-occur with the user's current cart contents. Scores are aggregated across all provided items using pre-computed co-occurrence patterns. Use on cart and checkout pages.

    Request body
    FieldRequiredDescription
    item_idsYesArray of item IDs currently in the cart.
    limitNoItems to return (default: 10).
    pageNoPagination offset (default: 1).
    basketRecs.ts
    const res = await fetch('https://recommendations.lehnz.com/recommend/basket', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'X-API-KEY': process.env.NEXT_PUBLIC_LEHNZ_PUBLISHABLE_KEY!,
    },
    body: JSON.stringify({ item_ids: cartItems.map(i => i.id), limit: 8 }),
    });

    Price-optimized recommendations

    POSThttps://recommendations.lehnz.com/recommend/price_optimized

    Returns personalized recommendations re-ranked according to the user's historical price bucket. This is a drop-in replacement for POST /recommend — identical request shape, same response format.

    Request body
    FieldRequiredDescription
    user_idYesThe user to generate recommendations for.
    limitNoItems to return (default: 10).
    pageNoPagination offset (default: 1).
    modeNoRecommendation mode (default: auto).
    filtersNoFree-form JSON filter object.
    Drop-in swap

    Change only the URL path from /recommend to /recommend/price_optimized. Request shape and response format are identical.

    priceOptRecs.ts
    // Drop-in replacement for POST /recommend — change only the URL
    const res = await fetch('https://recommendations.lehnz.com/recommend/price_optimized', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'X-API-KEY': process.env.NEXT_PUBLIC_LEHNZ_PUBLISHABLE_KEY!,
    },
    body: JSON.stringify({ user_id: userId, limit: 12, placement: 'home' }),
    });

    Full integration pattern

    Fetch recommendation IDs → hydrate with your product data → display with attribution tracking.

    recommendations.ts
    // app/actions/recommendations.ts
    async function getRecommendedProducts(userId: string, placement = 'home') {
    // 1. Fetch recommendation IDs from lehnz
    const res = await fetch('https://recommendations.lehnz.com/recommend', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'X-API-KEY': process.env.NEXT_PUBLIC_LEHNZ_PUBLISHABLE_KEY!,
    },
    body: JSON.stringify({ user_id: userId, limit: 12, placement }),
    });
    const { data } = await res.json();
    if (!data?.all_item_ids?.length) return [];
    // 2. Hydrate with your product data
    const products = await getProductsByIds(data.all_item_ids); // your own DB call
    // 3. Attach recommendation_id for attribution
    return products.map(p => ({
    ...p,
    recommendationId: data.recommendation_id,
    }));
    }
    recommendations.ts
    async function getRecommendedProducts(userId: string) {
    const res = await fetch('https://recommendations.lehnz.com/recommend', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'X-API-KEY': process.env.NEXT_PUBLIC_LEHNZ_PUBLISHABLE_KEY!,
    },
    body: JSON.stringify({ user_id: userId, limit: 12, placement: 'home' }),
    });
    const { data } = await res.json();
    const products = await fetch(`/api/products?ids=${data.all_item_ids.join(',')}`)
    .then(r => r.json());
    return products.map(p => ({ ...p, recommendationId: data.recommendation_id }));
    }
    recommendations.py
    import requests
    def get_recommendations(user_id: str, limit: int = 12) -> dict:
    res = requests.post(
    'https://recommendations.lehnz.com/recommend',
    headers={
    'X-API-KEY': 'lehnz_pk_YOUR_KEY',
    'Content-Type': 'application/json',
    },
    json={'user_id': user_id, 'limit': limit, 'placement': 'home'},
    )
    data = res.json()['data']
    return {
    'item_ids': data['all_item_ids'],
    'recommendation_id': data['recommendation_id'],
    }

    Displaying recommendations with tracking

    Attach the recommendation_id to your product components so clicks and purchases are attributed back to the recommendation.

    RecommendedProductCard.tsx
    function RecommendedProductCard({ product }) {
    const handleClick = async () => {
    await fetch('https://ingestion.lehnz.com/api/v1/events/ingest', {
    method: 'POST',
    headers: {
    'X-API-KEY': process.env.NEXT_PUBLIC_LEHNZ_PUBLISHABLE_KEY!,
    'Content-Type': 'application/json',
    },
    body: JSON.stringify([{
    user_id: getUserId(),
    event_name: 'click',
    item_id: product.id,
    recommendation_id: product.recommendationId,
    }]),
    keepalive: true,
    });
    };
    return (
    <div onClick={handleClick}>
    <img src={product.image} alt={product.name} />
    <h3>{product.name}</h3>
    <p>${product.price}</p>
    </div>
    );
    }

    Pagination

    Use page to load more results. meta.total_pages tells you how many pages are available.

    pagination.ts
    const res = await fetch('https://recommendations.lehnz.com/recommend', {
    method: 'POST',
    headers: { 'X-API-KEY': '...', 'Content-Type': 'application/json' },
    body: JSON.stringify({ user_id: userId, limit: 12, page: 2 }),
    });
    const { data } = await res.json();
    // data.meta.total_pages tells you how many pages are available

    What's next

    Tracking Events

    All event types, batching, attribution, and code examples.

    API Reference

    Full endpoint reference, headers, schemas, and rate limits.