Docs
    GuidesAPI Reference
    Sign inCreate account
    Overview

    Getting started

    API keysQuickstart

    Integration

    Load your catalogTracking EventsIdentity StitchingPersonalisation

    Production

    Errors & troubleshootingRetries & rate limits

    Reference

    API ReferenceVersioningChangelog
    HomeDocumentationAPI Reference
    Previous
    Retries & rate limits
    Next
    Versioning

    Skip the ML, Ship the Revenue

    Product

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

    Developers

    • Documentation

    Company

    • Contact

    © 2026 Lehnz, Inc. All rights reserved.

    Reference

    API Reference

    Headers, schemas, status codes, and rate limits for all lehnz endpoints. For worked examples, see the integration guides.

    Base URL

    Every endpoint shares one base URL; all paths are versioned under /v1.

    https://api.lehnz.com

    API keys

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

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

    Using a secret key on a publishable endpoint (or vice versa) returns 403 Forbidden. See API keys for rotation instructions.

    Headers

    HeaderRequiredValue
    X-API-KEYYesYour publishable or secret key
    Content-TypeYesapplication/json

    Ingestion endpoints

    All ingestion endpoints return 202 Accepted and use the same response envelope: { success, message, data: { accepted }, error }.

    POST /v1/ingest/items/upsert

    POSThttps://api.lehnz.com/v1/ingest/items/upsert

    Load your catalog before anything else; Lehnz can only recommend items it knows about. Re-call whenever items change. To hide or remove an item, upsert it with status: inactive or deleted rather than omitting it.

    Auth: Secret key (server-side only). Worked example: Load your catalog.

    Request body
    FieldRequiredDescription
    item_idYesStable item identifier.
    item_typeYesDomain-specific category, e.g. product or article.
    statusYesactive = recommendable; inactive = hidden; deleted = soft-deleted.
    attributesNoFree-form metadata (title, price, brand, category) used for filtering and ranking.
    created_atNoItem creation timestamp (ISO 8601).
    response.json
    {
      "success": true,
      "message": "items accepted",
      "data": { "accepted": 1 },
      "error": null
    }

    POST /v1/ingest/users/upsert

    POSThttps://api.lehnz.com/v1/ingest/users/upsert

    Load your users so recommendations can be personalised to them. Re-call when a profile changes or a user deactivates. Set status: inactive or deleted to preserve event history for analytics.

    Auth: Secret key (server-side only). Worked example: Load your catalog.

    Request body
    FieldRequiredDescription
    user_idYesStable user identifier (your application's user ID).
    statusYesactive = visible to recommendations; inactive = hidden, history kept; deleted = soft-deleted.
    created_atYesUser signup timestamp (ISO 8601).
    attributesNoFree-form metadata (segment, plan, locale).
    response.json
    {
      "success": true,
      "message": "users accepted",
      "data": { "accepted": 1 },
      "error": null
    }

    POST /v1/ingest/events/ingest

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

    Stream every meaningful interaction so Lehnz learns in real time. Accepts a single event object or an array. When an interaction came from a recommendation, include recommendation_id to close the attribution loop.

    Auth: Publishable key (browser-safe). Worked examples: Tracking Events.

    Request body (per event)
    FieldRequiredDescription
    user_idYesStable identifier. Anonymous shoppers use a client-generated UUID; signed-in shoppers use the application's real user ID.
    event_familyYesexposure | engagement | conversion | system
    event_nameYesLowercase event name. See Tracking Events for the standard names and their weights.
    previous_user_idNoRequired only for identify events: the prior anonymous ID being aliased.
    item_idNoNull when the event is not tied to a specific item.
    recommendation_idNoInclude when the event was triggered by a served recommendation.
    event_idNoClient-supplied UUID; server assigns one if omitted.
    contextNoFree-form context object (device, locale, session).
    response.json
    {
      "success": true,
      "message": "events accepted",
      "data": { "accepted": 1 },
      "error": null
    }

    Recommendations

    One endpoint, many strategies. POST /v1/recommend serves every use case; the strategy field picks the algorithm.

    POST /v1/recommend

    POSThttps://api.lehnz.com/v1/recommend

    Auth: Publishable key (browser-safe). See Recommendations for the full strategy list, when to use each, and worked examples.

    Request body
    FieldRequiredDescription
    strategyNoOne of 14 strategies (default personalized). See Recommendations.
    user_idNoRequired for user-based strategies.
    context_item_idNoRequired for similar, frequently-bought-together, frequently-consumed-together.
    filtersNoAttribute filters, e.g. { "category": "shoes" }.
    limitNoItems to return (default 20, max 100).
    pageNo1-indexed page number for pagination (default 1).
    response.json
    {
      "success": true,
      "message": "Success",
      "data": {
        "recommendation_id": "550e8400-e29b-41d4-a716-446655440000",
        "tenant_id": "glow-beauty-ng",
        "domain": "commerce",
        "strategy": "personalized",
        "mode": "behavioral",
        "results": [
          { "item_id": "prod_7", "score": 0.985, "reason": "behavioral_match", "metadata": { "brand": "Sony" } }
        ],
        "recommended_items": ["prod_7", "prod_3", "prod_22"],
        "pagination": { "page": 1, "limit": 20, "total_count": 48, "has_next": true },
        "latency_ms": 42.5
      },
      "error": null
    }

    Response envelope

    All responses share 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: data queued for async processing
    400Bad Request: validation error; check the 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 the payload entered the processing queue, not that it has been persisted. Events are typically available within seconds. See Errors & status codes for the full message catalog.

    Rate limits

    1,000 requests per 15 minutes per organisation, shared across all API keys. Auth endpoints (/auth/register, /auth/login) are capped at 10 requests per 15 minutes per IP. Batch multiple events into a single array to stay efficient.

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

    What's next

    Errors & status codes

    Every distinct error response, with example payloads and fixes.

    Personalisation

    Strategies, request body, and worked examples for /v1/recommend.