Generate
curl --request POST \
--url https://api.jeantechnologies.com/v1/generate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"tokenizer_id": "tok_9k2m",
"history": [
"sku_310",
"sku_884",
"sku_771"
],
"limit": 10,
"beam_width": 40,
"exclude_history": true,
"filters": {
"in_stock": true
}
}
'import requests
url = "https://api.jeantechnologies.com/v1/generate"
payload = {
"tokenizer_id": "tok_9k2m",
"history": ["sku_310", "sku_884", "sku_771"],
"limit": 10,
"beam_width": 40,
"exclude_history": True,
"filters": { "in_stock": True }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
tokenizer_id: 'tok_9k2m',
history: ['sku_310', 'sku_884', 'sku_771'],
limit: 10,
beam_width: 40,
exclude_history: true,
filters: {in_stock: true}
})
};
fetch('https://api.jeantechnologies.com/v1/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.jeantechnologies.com/v1/generate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'tokenizer_id' => 'tok_9k2m',
'history' => [
'sku_310',
'sku_884',
'sku_771'
],
'limit' => 10,
'beam_width' => 40,
'exclude_history' => true,
'filters' => [
'in_stock' => true
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.jeantechnologies.com/v1/generate"
payload := strings.NewReader("{\n \"tokenizer_id\": \"tok_9k2m\",\n \"history\": [\n \"sku_310\",\n \"sku_884\",\n \"sku_771\"\n ],\n \"limit\": 10,\n \"beam_width\": 40,\n \"exclude_history\": true,\n \"filters\": {\n \"in_stock\": true\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.jeantechnologies.com/v1/generate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"tokenizer_id\": \"tok_9k2m\",\n \"history\": [\n \"sku_310\",\n \"sku_884\",\n \"sku_771\"\n ],\n \"limit\": 10,\n \"beam_width\": 40,\n \"exclude_history\": true,\n \"filters\": {\n \"in_stock\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jeantechnologies.com/v1/generate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"tokenizer_id\": \"tok_9k2m\",\n \"history\": [\n \"sku_310\",\n \"sku_884\",\n \"sku_771\"\n ],\n \"limit\": 10,\n \"beam_width\": 40,\n \"exclude_history\": true,\n \"filters\": {\n \"in_stock\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"recommendations": [
{
"item_id": "sku_402",
"codes": [
1487,
302,
91,
12
],
"tokens": "<sid_0_1487><sid_1_302><sid_2_91><sid_3_12>",
"score": 0.31
}
],
"beams_explored": 40,
"beams_pruned_invalid": 0
}{
"error": {
"code": "invalid_request",
"message": "Field 'domain' is required.",
"details": {}
}
}Semantic IDs
Generate
Generate recommendations by autoregressively decoding semantic IDs.
POST
/
generate
Generate
curl --request POST \
--url https://api.jeantechnologies.com/v1/generate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"tokenizer_id": "tok_9k2m",
"history": [
"sku_310",
"sku_884",
"sku_771"
],
"limit": 10,
"beam_width": 40,
"exclude_history": true,
"filters": {
"in_stock": true
}
}
'import requests
url = "https://api.jeantechnologies.com/v1/generate"
payload = {
"tokenizer_id": "tok_9k2m",
"history": ["sku_310", "sku_884", "sku_771"],
"limit": 10,
"beam_width": 40,
"exclude_history": True,
"filters": { "in_stock": True }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
tokenizer_id: 'tok_9k2m',
history: ['sku_310', 'sku_884', 'sku_771'],
limit: 10,
beam_width: 40,
exclude_history: true,
filters: {in_stock: true}
})
};
fetch('https://api.jeantechnologies.com/v1/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.jeantechnologies.com/v1/generate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'tokenizer_id' => 'tok_9k2m',
'history' => [
'sku_310',
'sku_884',
'sku_771'
],
'limit' => 10,
'beam_width' => 40,
'exclude_history' => true,
'filters' => [
'in_stock' => true
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.jeantechnologies.com/v1/generate"
payload := strings.NewReader("{\n \"tokenizer_id\": \"tok_9k2m\",\n \"history\": [\n \"sku_310\",\n \"sku_884\",\n \"sku_771\"\n ],\n \"limit\": 10,\n \"beam_width\": 40,\n \"exclude_history\": true,\n \"filters\": {\n \"in_stock\": true\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.jeantechnologies.com/v1/generate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"tokenizer_id\": \"tok_9k2m\",\n \"history\": [\n \"sku_310\",\n \"sku_884\",\n \"sku_771\"\n ],\n \"limit\": 10,\n \"beam_width\": 40,\n \"exclude_history\": true,\n \"filters\": {\n \"in_stock\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jeantechnologies.com/v1/generate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"tokenizer_id\": \"tok_9k2m\",\n \"history\": [\n \"sku_310\",\n \"sku_884\",\n \"sku_771\"\n ],\n \"limit\": 10,\n \"beam_width\": 40,\n \"exclude_history\": true,\n \"filters\": {\n \"in_stock\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"recommendations": [
{
"item_id": "sku_402",
"codes": [
1487,
302,
91,
12
],
"tokens": "<sid_0_1487><sid_1_302><sid_2_91><sid_3_12>",
"score": 0.31
}
],
"beams_explored": 40,
"beams_pruned_invalid": 0
}{
"error": {
"code": "invalid_request",
"message": "Field 'domain' is required.",
"details": {}
}
}The value moment. Give the model a user’s history and it emits semantic ID tokens one level at a time, exactly the way a language model emits text.
Beam search is constrained to prefixes that exist in the codebook, so the model cannot hallucinate an item that does not exist. Every returned sequence resolves.
Filters are applied during decoding rather than after, so a restrictive
curl https://api.jeantechnologies.com/v1/generate \
-H "Authorization: Bearer $JEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tokenizer_id": "tok_9k2m",
"history": ["sku_310", "sku_884", "sku_771"],
"limit": 10,
"beam_width": 40,
"filters": { "in_stock": true }
}'
recs = requests.post(
"https://api.jeantechnologies.com/v1/generate",
headers={"Authorization": f"Bearer {os.environ['JEAN_API_KEY']}"},
json={
"tokenizer_id": "tok_9k2m",
"history": ["sku_310", "sku_884", "sku_771"],
"limit": 10,
"filters": {"in_stock": True},
},
).json()
const res = await fetch("https://api.jeantechnologies.com/v1/generate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.JEAN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tokenizer_id: "tok_9k2m",
history: ["sku_310", "sku_884", "sku_771"],
limit: 10,
filters: { in_stock: true },
}),
});
const { recommendations } = await res.json();
Response
{
"recommendations": [
{
"item_id": "sku_402",
"codes": [1487, 302, 91, 12],
"tokens": "<sid_0_1487><sid_1_302><sid_2_91><sid_3_12>",
"score": 0.31
}
],
"beams_explored": 40,
"beams_pruned_invalid": 0
}
score is length-normalized sequence likelihood. It is comparable between candidates in one response and not comparable across requests, so use it to rank, not to threshold.
beams_pruned_invalid should be 0. A nonzero value means beam search reached prefixes the codebook no longer resolves, which almost always means the serving codebook is stale relative to the catalog. Refit or re-sync before trusting the results.History matters
history is ordered, oldest first, and the order is signal. A user who viewed A then B is a different state from one who viewed B then A, and the model is trained to care.
Send the real sequence. Deduplicating it, sorting it, or collapsing it into a set throws away most of what makes a sequence model better than a co-occurrence table.
Long histories are truncated from the front, keeping the most recent interactions. If you have a strong reason to keep older context, say so during onboarding and we can weight the window differently for your tenant.
Tuning beam width
beam_width | Effect |
|---|---|
= limit | Fastest. Greedy in practice, and recall suffers on tail items. |
4x limit | Default territory. Good recall for most catalogs. |
10x limit | Diminishing returns on quality, meaningful latency cost. |
filters object needs a wider beam to fill limit. If you are getting back fewer results than you asked for, widen the beam before you loosen the filter.
Feeding outcomes back
Generation is not the end of the loop. Send what actually happened toPOST /feedback so the model adapts to your objective rather than to a proxy. See Foundation models for how the adaptation stages fit together.Authorizations
API key issued by Jean Technologies. Contact the team for access.
Body
application/json
Example:
"tok_9k2m"
The user's item interactions, oldest first. Order carries preference, so send it in true sequence.
Example:
["sku_310", "sku_884", "sku_771"]
Required range:
1 <= x <= 100Wider beams raise recall and latency. Must be at least limit.
Hard constraints applied to candidate items during decoding.
Example:
{ "in_stock": true }
Response
Recommendations
⌘I

