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
    HomeDocumentationAPI Reference
    Previous
    Troubleshooting
    Next
    Versioning

    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.

    Reference

    API Reference

    Headers, schemas, status codes, and rate limits for all lehnz endpoints.

    Base URLs

    ServiceBase URL
    Events & Ingestionhttps://ingestion.lehnz.com/api/v1
    Recommendationshttps://recommendations.lehnz.com

    API keys

    API keys are generated from the Developer Access tab in your lehnz dashboard. Every request requires an X-API-KEY header — no Bearer prefix.

    TypePrefixWhere to use
    Publishablelehnz_pk_...Browser and client-side code
    Secretlehnz_sk_...Server-side only — never expose in the browser

    The server enforces key type — using a secret key on a public endpoint (or vice versa) returns 403 Forbidden. See API keys for the full endpoint→key mapping and rotation instructions.

    Headers

    HeaderRequiredValue
    X-API-KEYYes (for pk_/sk_ paths)Your publishable or secret key
    AuthorizationYes (for dashboard JWT paths)Bearer <developer JWT>
    Content-TypeYesapplication/json (or multipart/form-data for /upload/*)
    X-DomainYescommerce

    Events

    POST /api/v1/events/ingest

    POSThttps://ingestion.lehnz.com/api/v1/events/ingest

    Track user interactions. Accepts a single event or an array of events.

    Auth: Publishable key

    request.json
    [
    {
    "user_id": "string", // required
    "event_name": "string", // required — see Standard Event Names
    "item_id": "string", // optional
    "session_id": "string", // optional
    "recommendation_id": "string", // optional — for attribution
    "previous_user_id": "string", // required only for identify events
    "context": {} // optional, any JSON
    }
    ]
    response
    202 Accepted
    { "success": true, "data": { "accepted": 1 } }

    Recommendations

    POST /recommend

    POSThttps://recommendations.lehnz.com/recommend

    Get a personalized ranked list of item IDs for a user.

    Auth: Publishable key

    request.json
    {
    "user_id": "string", // required
    "limit": 12, // optional, default: 12
    "page": 1, // optional, default: 1
    "placement": "home" // optional — home | pdp | cart | any custom string
    }
    response
    200 OK
    {
    "recommendation_id": "rec_abc123",
    "all_item_ids": ["prod_7", "prod_3", "prod_22"],
    "meta": { "total_items": 48, "total_pages": 4 }
    }

    GET /item/:item_id

    GEThttps://recommendations.lehnz.com/item/:item_id

    Get items semantically similar to a given item — for "Customers also viewed" sections.

    Auth: Publishable key

    query-params
    Query parameters:
    limit — number of items to return (default: 4)
    page — pagination offset (default: 1)
    mode — recommendation mode (default: semantic)
    response
    200 OK — same shape as POST /recommend

    POST /recommend/session

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

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

    Auth: Publishable key

    request.json
    {
    "clicked_item_id": "string", // required
    "limit": 10, // optional, default: 10
    "page": 1, // optional, default: 1
    "mode": "auto", // optional, default: auto
    "filters": {} // optional, any JSON
    }
    response
    200 OK
    {
    "all_item_ids": ["prod_5", "prod_18", "prod_9"],
    "item_id": "prod_42",
    "mode": "auto",
    "recommendations": [...],
    "meta": { "total_items": 24, "total_pages": 3 }
    }

    POST /recommend/basket

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

    Get 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.

    Auth: Publishable key

    request.json
    {
    "item_ids": ["string"], // required — array of current cart item IDs
    "limit": 10, // optional, default: 10
    "page": 1 // optional, default: 1
    }
    response
    200 OK
    {
    "all_item_ids": ["prod_11", "prod_7", "prod_33"],
    "basket_items": ["prod_2", "prod_8"],
    "recommendations": [...],
    "meta": { "total_items": 18, "total_pages": 2 },
    "source": "co_occurrence"
    }

    POST /recommend/price_optimized

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

    Personalized recommendations re-ranked by the user's historical price bucket. Drop-in replacement for POST /recommend — identical request shape, same response format.

    Auth: Publishable key

    request.json
    {
    "user_id": "string", // required
    "limit": 10, // optional, default: 10
    "page": 1, // optional, default: 1
    "mode": "auto", // optional, default: auto
    "filters": {} // optional, any JSON
    }
    response
    200 OK
    {
    "all_item_ids": ["prod_3", "prod_15", "prod_6"],
    "user_id": "usr_abc",
    "recommendations": [...],
    "meta": { "total_items": 48, "total_pages": 4 },
    "source": "price_optimized"
    }

    Standard event names

    Use these standard event_name values. Custom event names are also accepted — lehnz scores them using the event_family weight (engagement or conversion).

    event_nameWhen to fireImpact
    viewA product or item page loadsLow
    searchA user submits a search queryLow
    clickA user clicks a product from a list or recommendationMedium
    add_to_cartA user adds an item to their cartMedium-high
    remove_from_cartA user removes an item from their cartNegative signal
    checkout_startA user begins the checkout flowHigh
    purchaseA transaction completes successfullyHighest
    identifyUser signs in — merges anonymous + authenticated profiles—

    Response envelope

    All responses use the same structure:

    success.json
    { "success": true, "message": "...", "data": { } }
    error.json
    { "success": false, "message": "Human-readable error", "error": "Detail" }

    HTTP status codes

    StatusMeaning
    200OK — synchronous request succeeded
    202Accepted — event or data queued for async processing
    400Bad Request — validation error, check message field
    401Unauthorized — missing or invalid X-API-KEY
    403Forbidden — wrong key type for this endpoint
    429Rate Limited — back off and retry (see RateLimit-Reset header)
    500Internal Server Error

    202 Accepted means your data was accepted into the processing queue, not that it has been persisted yet. Events are typically available within seconds.

    See Errors & status codes for full message catalog and fixes.

    Rate limits

    1 000 requests per 15 minutes per organization, shared across all your API keys. Authentication endpoints (/auth/register, /auth/login) are limited separately to 10 requests per 15 minutes per IP.

    Batch multiple events into a single array instead of one request per event:

    batch.json
    // Good — one request for many events
    [
    { "user_id": "usr_1", "event_name": "view", "item_id": "prod_1" },
    { "user_id": "usr_1", "event_name": "click", "item_id": "prod_2" },
    { "user_id": "usr_1", "event_name": "add_to_cart", "item_id": "prod_2" }
    ]

    On 429, retry with exponential backoff. The RateLimit-Reset header indicates when you can try again. See Retries & rate limits for the full pattern.

    Data schemas

    Item

    item.json
    {
    "item_id": "string", // required
    "item_type": "product", // optional, default: "product"
    "status": "active | inactive | deleted", // optional, default: "active"
    "attributes": { // optional, any JSON
    "name": "...",
    "price": 0,
    "category": "...",
    "brand": "..."
    }
    }

    User

    user.json
    {
    "user_id": "string", // required
    "attributes": { // optional, any JSON
    "email": "...",
    "age": 0,
    "interests": []
    }
    }

    attributes is a free-form JSON object — include any fields meaningful to your domain. Richer attributes improve recommendation quality.

    What's next

    Errors & status codes

    Every distinct error response, with example payloads and fixes.

    TypeScript SDK

    A typed client that handles errors, retries, and types for you.