Create Customization
Create a new customization with a defined scope and pins list.
Overview
Important This endpoint requires HMAC authentication.
Create a new customization with a defined scope and pins list. This endpoint allows you to programmatically manage pins for specific items or criteria.
Authentication
This endpoint requires HMAC authentication. You must include the Date and Authorization headers. See Authentication for details.
https://live.luigisbox.tech/v1/recommender/pin/{TRACKER_ID}/scope
Request Parameters
To create a customization, send a POST request to the endpoint with the tracker_id in the path and the configuration in the body.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
TRACKER_ID |
String | ✓ | Your unique tracker identifier. |
Request Headers
| Header | Value | Description |
|---|---|---|
Content-Type |
application/json |
Required. |
Date |
HTTP Date | Required for HMAC. |
Authorization |
Signature | Required for HMAC. |
Request Body Attributes
| Parameter | Type | Required | Description |
|---|---|---|---|
pin_definitions |
Array | ✓ | List of Pin Objects to apply. |
model |
String | ✓ | The recommendation model (e.g., basket). |
target_type |
String | ✓ | The type of the target (e.g., item). |
target_identity |
String | Cond. | The unique identity of the target (e.g., product ID) if target_type is item. |
target_criteria |
Object | Cond. | The Criteria Object. Required if target_type is criteria. |
tags |
Array | List of tags (strings) for this scope. | |
target_metadata |
Object | Cond. | Metadata of the item (e.g., title, image). Required if target_type is item. |
Pin Object Attributes
| Parameter | Type | Required | Description |
|---|---|---|---|
position |
Integer | ✓ | Position of the pin. Use -1 for global, 0 for block. |
pin_type |
String | ✓ |
item or criteria. |
pin_identity |
String | Cond. | Item ID if pin_type is item. |
pin_criteria |
Object | Cond. | Criteria Object (if type is criteria). |
widget_id |
String | Widget ID for the pin. | |
is_block_pin |
Boolean | If true, this pin excludes items matching the identity/definition. |
|
is_bundle_pin |
Boolean | Whether this is a bundle pin. | |
active_from |
Date-time | Start time (ISO 8601). | |
active_to |
Date-time | End time (ISO 8601). |
Example Request
tracker_id="1234-5678"
private_key="your_private_api_key"
host="https://live.luigisbox.tech"
path="/v1/recommender/pin/${tracker_id}/scope"
method="POST"
content_type="application/json; charset=utf-8"
date=$(date -u "+%a, %d %b %Y %H:%M:%S GMT")
string_to_sign="$(printf "${method}\n${content_type}\n${date}\n${path}")"
signature=$(echo -n "${string_to_sign}" | openssl dgst -sha256 -hmac "${private_key}" -binary | base64)
curl -X ${method} "${host}${path}" \
-H "Content-Type: ${content_type}" \
-H "Date: ${date}" \
-H "Authorization: ApiAuth ${tracker_id}:${signature}" \
-d '{
"model": "basket",
"target_type": "item",
"target_identity": "/p/123",
"pin_definitions": []
}'
How to make a request
All requests to this endpoint must be authenticated using HMAC SHA-256. The examples on the right demonstrate the implementation in various languages, but the core logic follows these steps:
1. Construct the String to Sign
Create a string using the following components, separated by newlines (\n):
- HTTP Method:
POST - Content-Type:
application/json; charset=utf-8 - Date: The current timestamp in RFC 1123 format (e.g.,
Mon, 20 Jan 2025 12:00:00 GMT). - Request Path: The resource path.
2. Generate the HMAC Signature
- Create an HMAC SHA-256 hash of the string above using your Private API Key.
- Encode the result in Base64 and trim whitespace.
3. Send the Headers
Include Date, Content-Type, and Authorization: ApiAuth {TRACKER_ID}:{SIGNATURE} in your request.
Example Code
require 'faraday'
require 'base64'
require 'openssl'
require 'json'
require 'time'
def generate_luigisbox_digest(private_key, http_method, endpoint_path, date_header, content_type_header)
data = "#{http_method}\n#{content_type_header}\n#{date_header}\n#{endpoint_path}"
hash = OpenSSL::HMAC.digest('sha256', private_key, data)
Base64.strict_encode64(hash).strip
end
tracker_id = 'YOUR_TRACKER_ID'
private_key = 'your_private_api_key'
host = 'https://live.luigisbox.tech'
endpoint_path = "/v1/recommender/pin/#{tracker_id}/scope"
customization_data = {
"model": "basket",
"target_type": "item",
"target_identity": "/p/123",
"pin_definitions": []
}
conn = Faraday.new(url: host)
http_method = 'POST'
content_type = 'application/json; charset=utf-8'
date_header = Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")
signature = generate_luigisbox_digest(private_key, http_method, endpoint_path, date_header, content_type)
authorization_header = "ApiAuth #{tracker_id}:#{signature}"
response = conn.post(endpoint_path) do |req|
req.headers['Date'] = date_header
req.headers['Content-Type'] = content_type
req.headers['Authorization'] = authorization_header
req.body = customization_data.to_json
end
puts response.body
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
function generateLuigisboxDigest($privateKey, $httpMethod, $endpointPath, $dateHeader, $contentTypeHeader) {
$data = "{$httpMethod}\n{$contentTypeHeader}\n{$dateHeader}\n{$endpointPath}";
$hash = hash_hmac('sha256', $data, $privateKey, true);
return trim(base64_encode($hash));
}
$TRACKER_ID = "YOUR_TRACKER_ID";
$YOUR_PRIVATE_KEY = "your_private_api_key";
$LUIGISBOX_HOST = 'https://live.luigisbox.tech';
$ENDPOINT_PATH = "/v1/recommender/pin/{$TRACKER_ID}/scope";
$customization_data = [
"model" => "basket",
"target_type" => "item",
"target_identity" => "/p/123",
"pin_definitions" => []
];
$http_method = 'POST';
$content_type = 'application/json; charset=utf-8';
$current_date = gmdate('D, d M Y H:i:s') . ' GMT';
$signature = generateLuigisboxDigest($YOUR_PRIVATE_KEY, $http_method, $ENDPOINT_PATH, $current_date, $content_type);
$authorization_header = "ApiAuth {$TRACKER_ID}:{$signature}";
$client = new GuzzleHttp\Client();
$response = $client->request($http_method, "{$LUIGISBOX_HOST}{$ENDPOINT_PATH}", [
'headers' => [
'Content-Type' => $content_type,
'Date' => $current_date,
'Authorization' => $authorization_header,
],
'json' => $customization_data
]);
echo $response->getBody();
?>
const axios = require('axios');
const crypto = require('crypto');
function generateLuigisBoxDigest(privateKey, httpMethod, endpointPath, dateHeader, contentTypeHeader) {
const data = </span><span class="p">${</span><span class="nx">httpMethod</span><span class="p">}</span><span class="s2">\n</span><span class="p">${</span><span class="nx">contentTypeHeader</span><span class="p">}</span><span class="s2">\n</span><span class="p">${</span><span class="nx">dateHeader</span><span class="p">}</span><span class="s2">\n</span><span class="p">${</span><span class="nx">endpointPath</span><span class="p">}</span><span class="s2">;
const hmac = crypto.createHmac('sha256', privateKey);
hmac.update(data);
return hmac.digest('base64').trim();
}
const TRACKER_ID = "YOUR_TRACKER_ID";
const YOUR_PRIVATE_KEY = "your_private_api_key";
const LUIGISBOX_HOST = 'https://live.luigisbox.tech';
const ENDPOINT_PATH = /v1/recommender/pin/</span><span class="p">${</span><span class="nx">TRACKER_ID</span><span class="p">}</span><span class="s2">/scope;
const customizationData = {
model: "basket",
target_type: "item",
target_identity: "/p/123",
pin_definitions: []
};
const httpMethod = 'POST';
const contentType = 'application/json; charset=utf-8';
const dateHeader = new Date().toUTCString();
const signature = generateLuigisBoxDigest(YOUR_PRIVATE_KEY, httpMethod, ENDPOINT_PATH, dateHeader, contentType);
const authorizationHeader = ApiAuth </span><span class="p">${</span><span class="nx">TRACKER_ID</span><span class="p">}</span><span class="s2">:</span><span class="p">${</span><span class="nx">signature</span><span class="p">}</span><span class="s2">;
axios({
method: httpMethod,
url: </span><span class="p">${</span><span class="nx">LUIGISBOX_HOST</span><span class="p">}${</span><span class="nx">ENDPOINT_PATH</span><span class="p">}</span><span class="s2">,
headers: {
'Content-Type': contentType,
'Date': dateHeader,
'Authorization': authorizationHeader
},
data: customizationData
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
Response Structure
The response returns the created customization object with its unique ID.
Response Attributes
| Field | Type | Description |
|---|---|---|
id |
String | The unique identifier of the customization (scope). |
model |
String | The model used. |
target_type |
String | The target type. |
created_at |
String | Timestamp of creation. |
The Response Object
{
"id": "199620b4-df1a-46e8-ab59-9e9ed9af7106",
"model": "basket",
"target_type": "item",
"target_identity": "/p/123",
"created_at": "2025-01-20T12:00:00Z"
}
Error Handling
| HTTP Status | Description |
|---|---|
| 201 Created | Customization created successfully. |
| 400 Bad Request | Invalid configuration provided. |
| 401 Unauthorized | Missing or invalid authentication. |
| 404 Not Found | Tracker not found. |
| 422 Unprocessable Entity | Invalid pin definition provided. |
Error Responses
{
"reason": "Invalid pin definition provided",
"exception_details": {
"pin_definitions": ["Missing required field: position"],
"target_type": ["Must be one of: item, criteria, all"]
}
}