Skip to content

Product updates

Announcements

No active updates

API Principles

View MD

Luigi’s Box provides HTTP-based APIs for two main purposes: serving search results to users (Public) and managing your data/configuration (Private).

Auth: Requires only your public tracker_id.

Usage: Safe to call from Frontend (Browsers, Mobile Apps).

CategoryMethodBase URLEndpointDescription
SearchGET/POSTlive.luigisbox.com/searchFull-text search & facets.
AutocompleteGETlive.luigisbox.com/autocomplete/v2Prefix-based suggestions.
RecommenderPOSTlive.luigisbox.com/v1/recommendProduct recommendations.
Shopping AssistantPOSTlive.luigisbox.com/v1/assistantAI-powered structured dialogue that helps customers discover products.
Top itemsGETlive.luigisbox.com/v1/top_itemsMost popular items.
Trending queriesGETlive.luigisbox.com/v2/trending_queriesTrending search terms.
AnalyticsPOSTapi.luigisbox.com/v1Events API. Ingest user interactions.

Auth: Requires HMAC Signature using your Private Key. Usage: Backend Server ONLY.

Manage your product catalog.

MethodBase URLEndpointDescription
POSTlive.luigisbox.com/v1/contentCreate/Replace. Add new products.
PATCHlive.luigisbox.com/v1/contentPartial Update. Update specific fields.
DELETElive.luigisbox.com/v1/contentDelete. Remove products.
PATCHlive.luigisbox.com/v1/update_by_queryBatch Update. Update items matching a query.
GETlive.luigisbox.com/v1/content_exportExport. Download your current index data.

Manage pinning rules and batch recommendations.

MethodBase URLEndpointDescription
POSTlive.luigisbox.com/v1/recommender/pin/{ID}/scopesDefine pinning scopes (rules).
GETlive.luigisbox.com/v1/recommender/pin/{ID}/summaryGet pinning configuration summary.
POSTlive.luigisbox.com/v1/recommender/batching/{ID}/usersTrigger batch recommendation generation for users.
*live.luigisbox.com/v1/recommender/pin/*Various CRUD endpoints for managing pins.

Only the Private API endpoints require a custom HMAC-SHA256 signature.

You will need your API credentials found in Luigi’s Box App > Settings > Integration Settings:

  • Tracker_ID (Public Key): Identifies your account.
  • Secret Key (Private Key): Used to sign requests.

To authenticate, you must construct a specific “String to Sign,” hash it, and attach it as a header.

flowchart TD
A["HTTP method"]
B["Content-Type"]
C["Date header"]
D["Path"]
E["Canonical string"]
F{"Hash function"}
G["Raw bytes"]
H["Final signature"]
I["Authorization header"]
J["API server"]
Key["Private secret"]
A --> E
B --> E
C --> E
D --> E
E -->|HMAC SHA-256| F
Key -.-> F
F -->|Binary output| G
G -->|Base64 encode| H
H -->|Format string| I
I -->|Send| J

Every authenticated request must include these headers. The values used here must match the values used in the signature generation byte-for-byte.

HeaderDescription
DateThe current timestamp in HTTP Date format (e.g., Thu, 29 Jun 2017 12:11:16 GMT). Note: Our server clock tolerance is ±5 seconds. You must regenerate the date and signature for every request.
Content-TypeDescribes your payload (e.g., application/json; charset=utf-8).
AuthorizationThe authentication string. Format: AppName [tracker_id]:[signature]

Concatenate the following four strings, separated by a newline character (\n).

  1. HTTP Verb: Uppercase (e.g., POST, PUT, DELETE).
  2. Content-Type: Exactly as sent in the header (e.g., application/json; charset=utf-8).
  3. Date: Exactly as sent in the header.
  4. Resource Path: The absolute path excluding the query string (e.g., /v1/content, not /v1/content?foo=bar).
  1. Compute the HMAC-SHA256 digest of the Canonical String using your Secret Key.
  2. Encode the binary digest into a Base64 string.
require 'time'
require 'openssl'
require 'base64'
def digest(key, method, endpoint, date)
content_type = 'application/json; charset=utf-8'
data = "#{method}\n#{content_type}\n#{date}\n#{endpoint}"
dg = OpenSSL::Digest.new('sha256')
Base64.strict_encode64(OpenSSL::HMAC.digest(dg, key, data)).strip
end
date = Time.now.httpdate
digest("secret", "POST", "/v1/content", date)

Luigi’s Box relies on a unified user identity model across analytics and live APIs (Search, Autocomplete, Product Listing, and Recommender) to deliver effective personalization.

The platform tracks two distinct identity concepts:

  • Anonymous / Device user: A stable anonymous identifier for the current browser, device, or app install. It is not tied to a logged-in account. For integrations using the DataLayer collector, this value is typically available as the _lb cookie value. For fully custom API integrations, your application must generate, persist, and reuse this value across analytics events and live API requests.
  • Authenticated / Logged-in user: A stable identifier of the logged-in user in your application. This should be your own durable account or customer identifier, not a temporary request identifier.

Because the Events API (analytics) and Live APIs (Search, Autocomplete, etc.) refer to these concepts using different parameter names, it is essential to map them correctly.

When sending events to the Events API (api.luigisbox.com), you use the following parameters:

  • client_id: Carries the Anonymous / Device user identifier. You must always include client_id, and it must stay the same for the same browser or device, even after the user logs in or logs out.
  • customer_id: Carries the Authenticated / Logged-in user identifier. Send this alongside client_id when the user is logged in. Do not overwrite client_id with the customer identifier. See the Events API common parameters and Identity rules.
  • consent_granted: Set this to true when the user has accepted personalization cookies or equivalent consent. This is a consent flag, not an identifier, but it tells the Events API that the event can be used for personalization.

When querying live services (live.luigisbox.com) like Search, Autocomplete, Product Listing, or Recommender, the identity parameters map slightly differently to support personalization:

  • client_id: Passed to maintain the Anonymous / Device user identity. This should match the client_id sent in analytics. For integrations using the DataLayer collector, this value is typically available as the _lb cookie value.
  • user_id: Carries the identifier Luigi’s Box should personalize on for that request. It is not a third identity system. Its value must be one of the two identities defined above:
    • For anonymous users, set this to the client_id.
    • For authenticated users, set this to the customer_id.
    • Omit user_id entirely for non-personalized requests.

The following table summarizes the parameter mapping across the two API systems based on the user’s state:

In this table, Personalized describes the Live API behavior, while Consent Granted describes the Events API consent state that allows personalization.

User stateEvents APILive APIs
Anonymous
(Personalized / Consent Granted)
client_id = device ID
(e.g., browser-123)
consent_granted = true
client_id = device ID
user_id = device ID
Authenticated
(Personalized / Consent Granted)
client_id = device ID
customer_id = account ID (e.g., user-42)
consent_granted = true
client_id = device ID
user_id = account ID
Non-personalizedclient_id = device ID
customer_id = account ID (if authenticated)
consent_granted omitted or false
client_id = device ID
user_id omitted

We enforce rate limits to ensure stability. Limits are applied per Tracker ID (Account level) and per IP Address.

EndpointAccount LimitIP Limit
Content Updates500 req / min, 5 concurrent reqs-
Autocomplete800 req / min30 req / 5s
Search350 req / min30 req / 5s
Recommender60 req / 5s30 req / 5s

If you exceed a limit, you will receive a 429 Too Many Requests status. Your application must handle this gracefully.

We provide a Retry-After header indicating how many seconds you must wait.

sequenceDiagram
participant Client
participant API
Client->>API: POST content request
API-->>Client: 429 Retry-After 5 seconds
Note over Client: Wait 5 seconds
Client->>API: Retry content request
API-->>Client: 200 OK

Recommended Strategy:

  • Realtime APIs (Search, Autocomplete): Do not retry immediately. Discard the request.
  • Batch APIs (Content Updates): Use an exponential backoff strategy (wait Retry-After, then retry).

You should design your integration to be resilient to network failures.

CodeReasonTypeAction
401Auth FailedFatalCheck your Signature generation. The response body contains the string we expected vs. what you sent.
408TimeoutTransientSafe to retry once.
429ThrottlingTransientWait and retry (see above).
500Server ErrorFatalLog the error and contact support.
502Bad GatewayTransientUsually a deploy or network blip. Retry after 1s.
503Service UnavailableTransientCheck luigisboxstatus.com.

To ensure your integration is robust, we may enable Development Mode on your account during the integration phase.

What it does:

  • A small percentage of your requests will deliberately fail with various error codes (408, 429, 500).
  • These errors are marked in the JSON body as development_mode: true.

Why: This forces your developers to write proper error handling and retry logic before you go to production.