curl --request POST \
--url https://salespilot.crossup.ai/v1/recommendations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"connection_id": "<string>",
"placement_key": "<string>",
"context_item_id": "<string>",
"cart_items": [
{
"item_id": "<string>",
"variant_id": "<string>",
"quantity": 2
}
],
"cart_id": "<string>",
"client": {
"page_url": "<string>",
"referrer": "<string>",
"utm": {
"source": "<string>",
"medium": "<string>",
"campaign": "<string>",
"term": "<string>",
"content": "<string>"
},
"languages": [
"<string>"
],
"timezone": "<string>",
"screen": {
"width": 1,
"height": 1,
"pixel_ratio": 1
},
"viewport": {
"width": 1,
"height": 1,
"pixel_ratio": 1
},
"connection": {
"effective_type": "<string>",
"downlink_mbps": 1,
"rtt_ms": 1,
"save_data": true
},
"device": {
"mobile": true,
"platform": "<string>",
"touch_points": 1,
"memory_gb": 1,
"cpu_cores": 1
}
}
}
'import requests
url = "https://salespilot.crossup.ai/v1/recommendations"
payload = {
"connection_id": "<string>",
"placement_key": "<string>",
"context_item_id": "<string>",
"cart_items": [
{
"item_id": "<string>",
"variant_id": "<string>",
"quantity": 2
}
],
"cart_id": "<string>",
"client": {
"page_url": "<string>",
"referrer": "<string>",
"utm": {
"source": "<string>",
"medium": "<string>",
"campaign": "<string>",
"term": "<string>",
"content": "<string>"
},
"languages": ["<string>"],
"timezone": "<string>",
"screen": {
"width": 1,
"height": 1,
"pixel_ratio": 1
},
"viewport": {
"width": 1,
"height": 1,
"pixel_ratio": 1
},
"connection": {
"effective_type": "<string>",
"downlink_mbps": 1,
"rtt_ms": 1,
"save_data": True
},
"device": {
"mobile": True,
"platform": "<string>",
"touch_points": 1,
"memory_gb": 1,
"cpu_cores": 1
}
}
}
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({
connection_id: '<string>',
placement_key: '<string>',
context_item_id: '<string>',
cart_items: [{item_id: '<string>', variant_id: '<string>', quantity: 2}],
cart_id: '<string>',
client: {
page_url: '<string>',
referrer: '<string>',
utm: {
source: '<string>',
medium: '<string>',
campaign: '<string>',
term: '<string>',
content: '<string>'
},
languages: ['<string>'],
timezone: '<string>',
screen: {width: 1, height: 1, pixel_ratio: 1},
viewport: {width: 1, height: 1, pixel_ratio: 1},
connection: {effective_type: '<string>', downlink_mbps: 1, rtt_ms: 1, save_data: true},
device: {
mobile: true,
platform: '<string>',
touch_points: 1,
memory_gb: 1,
cpu_cores: 1
}
}
})
};
fetch('https://salespilot.crossup.ai/v1/recommendations', 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://salespilot.crossup.ai/v1/recommendations",
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([
'connection_id' => '<string>',
'placement_key' => '<string>',
'context_item_id' => '<string>',
'cart_items' => [
[
'item_id' => '<string>',
'variant_id' => '<string>',
'quantity' => 2
]
],
'cart_id' => '<string>',
'client' => [
'page_url' => '<string>',
'referrer' => '<string>',
'utm' => [
'source' => '<string>',
'medium' => '<string>',
'campaign' => '<string>',
'term' => '<string>',
'content' => '<string>'
],
'languages' => [
'<string>'
],
'timezone' => '<string>',
'screen' => [
'width' => 1,
'height' => 1,
'pixel_ratio' => 1
],
'viewport' => [
'width' => 1,
'height' => 1,
'pixel_ratio' => 1
],
'connection' => [
'effective_type' => '<string>',
'downlink_mbps' => 1,
'rtt_ms' => 1,
'save_data' => true
],
'device' => [
'mobile' => true,
'platform' => '<string>',
'touch_points' => 1,
'memory_gb' => 1,
'cpu_cores' => 1
]
]
]),
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://salespilot.crossup.ai/v1/recommendations"
payload := strings.NewReader("{\n \"connection_id\": \"<string>\",\n \"placement_key\": \"<string>\",\n \"context_item_id\": \"<string>\",\n \"cart_items\": [\n {\n \"item_id\": \"<string>\",\n \"variant_id\": \"<string>\",\n \"quantity\": 2\n }\n ],\n \"cart_id\": \"<string>\",\n \"client\": {\n \"page_url\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm\": {\n \"source\": \"<string>\",\n \"medium\": \"<string>\",\n \"campaign\": \"<string>\",\n \"term\": \"<string>\",\n \"content\": \"<string>\"\n },\n \"languages\": [\n \"<string>\"\n ],\n \"timezone\": \"<string>\",\n \"screen\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"viewport\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"connection\": {\n \"effective_type\": \"<string>\",\n \"downlink_mbps\": 1,\n \"rtt_ms\": 1,\n \"save_data\": true\n },\n \"device\": {\n \"mobile\": true,\n \"platform\": \"<string>\",\n \"touch_points\": 1,\n \"memory_gb\": 1,\n \"cpu_cores\": 1\n }\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://salespilot.crossup.ai/v1/recommendations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"connection_id\": \"<string>\",\n \"placement_key\": \"<string>\",\n \"context_item_id\": \"<string>\",\n \"cart_items\": [\n {\n \"item_id\": \"<string>\",\n \"variant_id\": \"<string>\",\n \"quantity\": 2\n }\n ],\n \"cart_id\": \"<string>\",\n \"client\": {\n \"page_url\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm\": {\n \"source\": \"<string>\",\n \"medium\": \"<string>\",\n \"campaign\": \"<string>\",\n \"term\": \"<string>\",\n \"content\": \"<string>\"\n },\n \"languages\": [\n \"<string>\"\n ],\n \"timezone\": \"<string>\",\n \"screen\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"viewport\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"connection\": {\n \"effective_type\": \"<string>\",\n \"downlink_mbps\": 1,\n \"rtt_ms\": 1,\n \"save_data\": true\n },\n \"device\": {\n \"mobile\": true,\n \"platform\": \"<string>\",\n \"touch_points\": 1,\n \"memory_gb\": 1,\n \"cpu_cores\": 1\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://salespilot.crossup.ai/v1/recommendations")
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 \"connection_id\": \"<string>\",\n \"placement_key\": \"<string>\",\n \"context_item_id\": \"<string>\",\n \"cart_items\": [\n {\n \"item_id\": \"<string>\",\n \"variant_id\": \"<string>\",\n \"quantity\": 2\n }\n ],\n \"cart_id\": \"<string>\",\n \"client\": {\n \"page_url\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm\": {\n \"source\": \"<string>\",\n \"medium\": \"<string>\",\n \"campaign\": \"<string>\",\n \"term\": \"<string>\",\n \"content\": \"<string>\"\n },\n \"languages\": [\n \"<string>\"\n ],\n \"timezone\": \"<string>\",\n \"screen\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"viewport\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"connection\": {\n \"effective_type\": \"<string>\",\n \"downlink_mbps\": 1,\n \"rtt_ms\": 1,\n \"save_data\": true\n },\n \"device\": {\n \"mobile\": true,\n \"platform\": \"<string>\",\n \"touch_points\": 1,\n \"memory_gb\": 1,\n \"cpu_cores\": 1\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"decision_id": "<string>",
"request_id": "<string>",
"store_id": "<string>",
"connection_id": "<string>",
"placement_key": "<string>",
"surface": "pdp",
"context": {
"cart_items": [
{
"item_id": "<string>",
"variant_id": "<string>",
"quantity": 2
}
],
"shooter": {
"item_id": "<string>",
"product": {
"item": {
"item_id": "<string>",
"store_id": "<string>",
"connection_id": "<string>",
"external_id": "<string>",
"title": {},
"status": "<string>",
"source_version": "<string>",
"primary_media": {
"url": "<string>",
"alt": {}
},
"description": {},
"handles": {},
"urls": {},
"media": [
{
"url": "<string>",
"alt": {}
}
],
"brand": "<string>",
"tags": [
"<string>"
],
"free_shipping": true,
"taxonomy": [
{
"taxonomy_id": "<string>",
"external_id": "<string>",
"name": {},
"handles": {},
"parent_id": "<string>"
}
]
},
"variants": [
{
"variant_id": "<string>",
"item_id": "<string>",
"external_id": "<string>",
"status": "<string>",
"sku": "<string>",
"title": {},
"price": {
"amount": "<string>",
"currency": "<string>"
},
"promotional_price": {
"amount": "<string>",
"currency": "<string>"
},
"attributes": [
{
"name": {},
"value": {}
}
]
}
],
"availability": [
{
"variant_id": "<string>",
"sellable": "<string>",
"as_of": "2023-11-07T05:31:56Z",
"quantity": 123
}
],
"refresh_revision": 2
}
}
},
"results": [
{
"item_id": "<string>",
"position": 2,
"reason_codes": [
"<string>"
],
"variant_id": "<string>",
"product": {
"item": {
"item_id": "<string>",
"store_id": "<string>",
"connection_id": "<string>",
"external_id": "<string>",
"title": {},
"status": "<string>",
"source_version": "<string>",
"primary_media": {
"url": "<string>",
"alt": {}
},
"description": {},
"handles": {},
"urls": {},
"media": [
{
"url": "<string>",
"alt": {}
}
],
"brand": "<string>",
"tags": [
"<string>"
],
"free_shipping": true,
"taxonomy": [
{
"taxonomy_id": "<string>",
"external_id": "<string>",
"name": {},
"handles": {},
"parent_id": "<string>"
}
]
},
"variants": [
{
"variant_id": "<string>",
"item_id": "<string>",
"external_id": "<string>",
"status": "<string>",
"sku": "<string>",
"title": {},
"price": {
"amount": "<string>",
"currency": "<string>"
},
"promotional_price": {
"amount": "<string>",
"currency": "<string>"
},
"attributes": [
{
"name": {},
"value": {}
}
]
}
],
"availability": [
{
"variant_id": "<string>",
"sellable": "<string>",
"as_of": "2023-11-07T05:31:56Z",
"quantity": 123
}
],
"refresh_revision": 2
}
}
],
"reason_codes": [
"<string>"
],
"generated_at": "2023-11-07T05:31:56Z",
"visitor": {
"visitor_id": "<string>",
"session_id": "<string>"
}
}{
"type": "https://api.crossup.ai/salespilot/errors/invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "<string>",
"code": "invalid_request",
"request_id": "<string>",
"errors": [
{
"code": "<string>",
"detail": "<string>",
"pointer": "<string>"
}
]
}{
"type": "https://api.crossup.ai/salespilot/errors/unauthorized",
"title": "Authentication required",
"status": 401,
"detail": "<string>",
"code": "unauthorized",
"request_id": "<string>"
}{
"type": "https://api.crossup.ai/salespilot/errors/forbidden-connection",
"title": "Connection is not accessible",
"status": 403,
"detail": "<string>",
"code": "forbidden_connection",
"request_id": "<string>"
}{
"type": "https://api.crossup.ai/salespilot/errors/not-found",
"title": "Resource not found",
"status": 404,
"detail": "<string>",
"code": "not_found",
"request_id": "<string>"
}{
"type": "https://api.crossup.ai/salespilot/errors/cart-items-limit-exceeded",
"title": "Cart item limit exceeded",
"status": 422,
"detail": "<string>",
"code": "cart_items_limit_exceeded",
"request_id": "<string>",
"max_items_per_cart": 200,
"actual_items": 2
}{
"type": "https://api.crossup.ai/salespilot/errors/rate-limited",
"title": "Too many requests",
"status": 429,
"detail": "<string>",
"code": "rate_limited",
"request_id": "<string>"
}{
"type": "https://api.crossup.ai/salespilot/errors/internal-error",
"title": "Internal server error",
"status": 500,
"detail": "<string>",
"code": "internal_error",
"request_id": "<string>"
}Pedir uma recomendação
Devolve a recomendação para um momento do storefront: os produtos em ordem, cada um já projetado no catálogo canônico.
curl --request POST \
--url https://salespilot.crossup.ai/v1/recommendations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"connection_id": "<string>",
"placement_key": "<string>",
"context_item_id": "<string>",
"cart_items": [
{
"item_id": "<string>",
"variant_id": "<string>",
"quantity": 2
}
],
"cart_id": "<string>",
"client": {
"page_url": "<string>",
"referrer": "<string>",
"utm": {
"source": "<string>",
"medium": "<string>",
"campaign": "<string>",
"term": "<string>",
"content": "<string>"
},
"languages": [
"<string>"
],
"timezone": "<string>",
"screen": {
"width": 1,
"height": 1,
"pixel_ratio": 1
},
"viewport": {
"width": 1,
"height": 1,
"pixel_ratio": 1
},
"connection": {
"effective_type": "<string>",
"downlink_mbps": 1,
"rtt_ms": 1,
"save_data": true
},
"device": {
"mobile": true,
"platform": "<string>",
"touch_points": 1,
"memory_gb": 1,
"cpu_cores": 1
}
}
}
'import requests
url = "https://salespilot.crossup.ai/v1/recommendations"
payload = {
"connection_id": "<string>",
"placement_key": "<string>",
"context_item_id": "<string>",
"cart_items": [
{
"item_id": "<string>",
"variant_id": "<string>",
"quantity": 2
}
],
"cart_id": "<string>",
"client": {
"page_url": "<string>",
"referrer": "<string>",
"utm": {
"source": "<string>",
"medium": "<string>",
"campaign": "<string>",
"term": "<string>",
"content": "<string>"
},
"languages": ["<string>"],
"timezone": "<string>",
"screen": {
"width": 1,
"height": 1,
"pixel_ratio": 1
},
"viewport": {
"width": 1,
"height": 1,
"pixel_ratio": 1
},
"connection": {
"effective_type": "<string>",
"downlink_mbps": 1,
"rtt_ms": 1,
"save_data": True
},
"device": {
"mobile": True,
"platform": "<string>",
"touch_points": 1,
"memory_gb": 1,
"cpu_cores": 1
}
}
}
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({
connection_id: '<string>',
placement_key: '<string>',
context_item_id: '<string>',
cart_items: [{item_id: '<string>', variant_id: '<string>', quantity: 2}],
cart_id: '<string>',
client: {
page_url: '<string>',
referrer: '<string>',
utm: {
source: '<string>',
medium: '<string>',
campaign: '<string>',
term: '<string>',
content: '<string>'
},
languages: ['<string>'],
timezone: '<string>',
screen: {width: 1, height: 1, pixel_ratio: 1},
viewport: {width: 1, height: 1, pixel_ratio: 1},
connection: {effective_type: '<string>', downlink_mbps: 1, rtt_ms: 1, save_data: true},
device: {
mobile: true,
platform: '<string>',
touch_points: 1,
memory_gb: 1,
cpu_cores: 1
}
}
})
};
fetch('https://salespilot.crossup.ai/v1/recommendations', 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://salespilot.crossup.ai/v1/recommendations",
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([
'connection_id' => '<string>',
'placement_key' => '<string>',
'context_item_id' => '<string>',
'cart_items' => [
[
'item_id' => '<string>',
'variant_id' => '<string>',
'quantity' => 2
]
],
'cart_id' => '<string>',
'client' => [
'page_url' => '<string>',
'referrer' => '<string>',
'utm' => [
'source' => '<string>',
'medium' => '<string>',
'campaign' => '<string>',
'term' => '<string>',
'content' => '<string>'
],
'languages' => [
'<string>'
],
'timezone' => '<string>',
'screen' => [
'width' => 1,
'height' => 1,
'pixel_ratio' => 1
],
'viewport' => [
'width' => 1,
'height' => 1,
'pixel_ratio' => 1
],
'connection' => [
'effective_type' => '<string>',
'downlink_mbps' => 1,
'rtt_ms' => 1,
'save_data' => true
],
'device' => [
'mobile' => true,
'platform' => '<string>',
'touch_points' => 1,
'memory_gb' => 1,
'cpu_cores' => 1
]
]
]),
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://salespilot.crossup.ai/v1/recommendations"
payload := strings.NewReader("{\n \"connection_id\": \"<string>\",\n \"placement_key\": \"<string>\",\n \"context_item_id\": \"<string>\",\n \"cart_items\": [\n {\n \"item_id\": \"<string>\",\n \"variant_id\": \"<string>\",\n \"quantity\": 2\n }\n ],\n \"cart_id\": \"<string>\",\n \"client\": {\n \"page_url\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm\": {\n \"source\": \"<string>\",\n \"medium\": \"<string>\",\n \"campaign\": \"<string>\",\n \"term\": \"<string>\",\n \"content\": \"<string>\"\n },\n \"languages\": [\n \"<string>\"\n ],\n \"timezone\": \"<string>\",\n \"screen\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"viewport\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"connection\": {\n \"effective_type\": \"<string>\",\n \"downlink_mbps\": 1,\n \"rtt_ms\": 1,\n \"save_data\": true\n },\n \"device\": {\n \"mobile\": true,\n \"platform\": \"<string>\",\n \"touch_points\": 1,\n \"memory_gb\": 1,\n \"cpu_cores\": 1\n }\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://salespilot.crossup.ai/v1/recommendations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"connection_id\": \"<string>\",\n \"placement_key\": \"<string>\",\n \"context_item_id\": \"<string>\",\n \"cart_items\": [\n {\n \"item_id\": \"<string>\",\n \"variant_id\": \"<string>\",\n \"quantity\": 2\n }\n ],\n \"cart_id\": \"<string>\",\n \"client\": {\n \"page_url\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm\": {\n \"source\": \"<string>\",\n \"medium\": \"<string>\",\n \"campaign\": \"<string>\",\n \"term\": \"<string>\",\n \"content\": \"<string>\"\n },\n \"languages\": [\n \"<string>\"\n ],\n \"timezone\": \"<string>\",\n \"screen\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"viewport\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"connection\": {\n \"effective_type\": \"<string>\",\n \"downlink_mbps\": 1,\n \"rtt_ms\": 1,\n \"save_data\": true\n },\n \"device\": {\n \"mobile\": true,\n \"platform\": \"<string>\",\n \"touch_points\": 1,\n \"memory_gb\": 1,\n \"cpu_cores\": 1\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://salespilot.crossup.ai/v1/recommendations")
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 \"connection_id\": \"<string>\",\n \"placement_key\": \"<string>\",\n \"context_item_id\": \"<string>\",\n \"cart_items\": [\n {\n \"item_id\": \"<string>\",\n \"variant_id\": \"<string>\",\n \"quantity\": 2\n }\n ],\n \"cart_id\": \"<string>\",\n \"client\": {\n \"page_url\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm\": {\n \"source\": \"<string>\",\n \"medium\": \"<string>\",\n \"campaign\": \"<string>\",\n \"term\": \"<string>\",\n \"content\": \"<string>\"\n },\n \"languages\": [\n \"<string>\"\n ],\n \"timezone\": \"<string>\",\n \"screen\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"viewport\": {\n \"width\": 1,\n \"height\": 1,\n \"pixel_ratio\": 1\n },\n \"connection\": {\n \"effective_type\": \"<string>\",\n \"downlink_mbps\": 1,\n \"rtt_ms\": 1,\n \"save_data\": true\n },\n \"device\": {\n \"mobile\": true,\n \"platform\": \"<string>\",\n \"touch_points\": 1,\n \"memory_gb\": 1,\n \"cpu_cores\": 1\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"decision_id": "<string>",
"request_id": "<string>",
"store_id": "<string>",
"connection_id": "<string>",
"placement_key": "<string>",
"surface": "pdp",
"context": {
"cart_items": [
{
"item_id": "<string>",
"variant_id": "<string>",
"quantity": 2
}
],
"shooter": {
"item_id": "<string>",
"product": {
"item": {
"item_id": "<string>",
"store_id": "<string>",
"connection_id": "<string>",
"external_id": "<string>",
"title": {},
"status": "<string>",
"source_version": "<string>",
"primary_media": {
"url": "<string>",
"alt": {}
},
"description": {},
"handles": {},
"urls": {},
"media": [
{
"url": "<string>",
"alt": {}
}
],
"brand": "<string>",
"tags": [
"<string>"
],
"free_shipping": true,
"taxonomy": [
{
"taxonomy_id": "<string>",
"external_id": "<string>",
"name": {},
"handles": {},
"parent_id": "<string>"
}
]
},
"variants": [
{
"variant_id": "<string>",
"item_id": "<string>",
"external_id": "<string>",
"status": "<string>",
"sku": "<string>",
"title": {},
"price": {
"amount": "<string>",
"currency": "<string>"
},
"promotional_price": {
"amount": "<string>",
"currency": "<string>"
},
"attributes": [
{
"name": {},
"value": {}
}
]
}
],
"availability": [
{
"variant_id": "<string>",
"sellable": "<string>",
"as_of": "2023-11-07T05:31:56Z",
"quantity": 123
}
],
"refresh_revision": 2
}
}
},
"results": [
{
"item_id": "<string>",
"position": 2,
"reason_codes": [
"<string>"
],
"variant_id": "<string>",
"product": {
"item": {
"item_id": "<string>",
"store_id": "<string>",
"connection_id": "<string>",
"external_id": "<string>",
"title": {},
"status": "<string>",
"source_version": "<string>",
"primary_media": {
"url": "<string>",
"alt": {}
},
"description": {},
"handles": {},
"urls": {},
"media": [
{
"url": "<string>",
"alt": {}
}
],
"brand": "<string>",
"tags": [
"<string>"
],
"free_shipping": true,
"taxonomy": [
{
"taxonomy_id": "<string>",
"external_id": "<string>",
"name": {},
"handles": {},
"parent_id": "<string>"
}
]
},
"variants": [
{
"variant_id": "<string>",
"item_id": "<string>",
"external_id": "<string>",
"status": "<string>",
"sku": "<string>",
"title": {},
"price": {
"amount": "<string>",
"currency": "<string>"
},
"promotional_price": {
"amount": "<string>",
"currency": "<string>"
},
"attributes": [
{
"name": {},
"value": {}
}
]
}
],
"availability": [
{
"variant_id": "<string>",
"sellable": "<string>",
"as_of": "2023-11-07T05:31:56Z",
"quantity": 123
}
],
"refresh_revision": 2
}
}
],
"reason_codes": [
"<string>"
],
"generated_at": "2023-11-07T05:31:56Z",
"visitor": {
"visitor_id": "<string>",
"session_id": "<string>"
}
}{
"type": "https://api.crossup.ai/salespilot/errors/invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "<string>",
"code": "invalid_request",
"request_id": "<string>",
"errors": [
{
"code": "<string>",
"detail": "<string>",
"pointer": "<string>"
}
]
}{
"type": "https://api.crossup.ai/salespilot/errors/unauthorized",
"title": "Authentication required",
"status": 401,
"detail": "<string>",
"code": "unauthorized",
"request_id": "<string>"
}{
"type": "https://api.crossup.ai/salespilot/errors/forbidden-connection",
"title": "Connection is not accessible",
"status": 403,
"detail": "<string>",
"code": "forbidden_connection",
"request_id": "<string>"
}{
"type": "https://api.crossup.ai/salespilot/errors/not-found",
"title": "Resource not found",
"status": 404,
"detail": "<string>",
"code": "not_found",
"request_id": "<string>"
}{
"type": "https://api.crossup.ai/salespilot/errors/cart-items-limit-exceeded",
"title": "Cart item limit exceeded",
"status": 422,
"detail": "<string>",
"code": "cart_items_limit_exceeded",
"request_id": "<string>",
"max_items_per_cart": 200,
"actual_items": 2
}{
"type": "https://api.crossup.ai/salespilot/errors/rate-limited",
"title": "Too many requests",
"status": 429,
"detail": "<string>",
"code": "rate_limited",
"request_id": "<string>"
}{
"type": "https://api.crossup.ai/salespilot/errors/internal-error",
"title": "Internal server error",
"status": 500,
"detail": "<string>",
"code": "internal_error",
"request_id": "<string>"
}Os cinco momentos
surface | Quando | O que é preciso |
|---|---|---|
pdp | Página de produto | context_item_id (o produto de partida) ou pelo menos um item em cart_items |
cart | Ao adicionar ao carrinho (o popup, não a página do carrinho) | idem |
success-page | Compra concluída | pelo menos um item em cart_items |
in-checkout | Dentro do checkout | pelo menos um item em cart_items |
carousel | A página do carrinho | pelo menos um item em cart_items |
400 invalid_request e pointer
diz qual campo. Um context_item_id em um momento de carrinho volta em
context, mas não muda a recomendação.
A requisição não escolhe a loja
Não existestore_id: o servidor tira a loja da chave e valida que
connection_id seja dela. Nenhum campo do corpo lê dados alheios.
O visitante
visitor é opcional: { visitor_id, session_id? }, com a forma vis_… e
ses_…. Nunca faz a requisição falhar: com outra forma, é descartado e não é
salvo. Nunca é um dado do comprador:
Visitante e contexto.
Cada requisição fica registrada com seu visitante e a recomendação que devolveu:
assim um clique é ligado depois a ela.
O que devolve
A resposta é a recomendação (na API,Decision: a lista de produtos recomendados para aquele momento).
decision_id: o id da recomendação, único por resposta. Duas requisições iguais são duas recomendações.request_id: o mesmo valor do headerX-Request-ID.context: de onde partiu a recomendação.shootertraz o produto de partida, ecart_items, o carrinho como chegou.results[]:item_id,variant_id?,position,reason_codes[]eproduct, completo: item, taxonomia, variantes com preço e disponibilidade.
score nem id da sugestão do motor. O ranking é a position, e um
teste do contrato falha se aparecer uma pontuação.product é opcional: se não deu para lê-lo, o resultado sai sem ele e se
resolve com ler o catálogo. item.description
viaja como a plataforma a manda; a Nuvemshop manda HTML, então sanitize.
reason_codes aparece na recomendação e em cada resultado: um explica a
resposta inteira, o outro essa posição. Numa lista vazia, diz o que aconteceu:
| Código | O que aconteceu |
|---|---|
no_offer | O motor não tem nada para esse momento. |
module_not_configured | A loja não tem esse momento ativado. |
missing_price | Um item chegou sem preço, e o motor precisa dele. |
unknown_external_id | O motor recomendou algo que o catálogo ainda não tem; é omitido. |
brain_unavailable | O motor não respondeu a tempo. A loja continua vendendo. |
brain_error:<status> | O motor rejeitou a consulta com esse status. |
cart_items é um array de objetos
Opcional (omitido é []), mas nunca null. Cada elemento é
{ item_id, variant_id, quantity }, com quantity ≥ 1. Passado o limite, a
resposta é cart_items_limit_exceeded,
com max_items_per_cart e actual_items.Autorizações
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Corpo
Every field but the connection, the placement and the surface is optional in the schema, and the surface decides what is needed. pdp, cart and checkout need a shooter (context_item_id) or at least one cart item. success-page, in-checkout and carousel need at least one cart item; a shooter sent with them is recorded and echoed but does not drive the engine. A request with neither is a 400.
cart_id is the store's own id for the cart and belongs with cart_items: send it whenever the cart is not empty. It is not required by the schema — a request without it is served normally — but the decision it produces cannot be tied back to a sale.
11The storefront moment that asks for recommendations. Three moments start from a product the shopper is looking at or just added (the shooter, context_item_id): pdp (product page), cart (right after adding to the cart) and checkout (when the purchase starts). The other three read only the cart: success-page (purchase finished), in-checkout (inside the checkout) and carousel (the cart page).
pdp, cart, checkout, success-page, in-checkout, carousel 1The shooter item (the product the moment starts from), when the moment has one.
1The cart as the storefront sees it. Omitted means empty.
Show child attributes
Show child attributes
The store's own id for this cart. Send it whenever cart_items is not empty: it is what ties the sale back to the offer once the order comes in through the webhook. A request that carries a cart without it still answers 200 and still serves a recommendation, but that decision cannot be attributed to a sale later.
1 - 256Pseudonymous identity of the browser that asks. The storefront SDK creates and keeps it; it carries no personal data and must never be an email, a phone number or a platform customer id. Sending it is optional, and a visitor that does not match this shape never fails the request: the server drops it, answers without it and does not store it.
Show child attributes
Show child attributes
What the storefront SDK can read in the browser about the request. Every field is optional and sending it never fails the request: a context the server cannot read is dropped and the recommendation is served anyway. The server also records the client IP, User-Agent, Accept-Language, Origin and Referer from the HTTP request; none of this is returned.
Show child attributes
Show child attributes
Resposta
Recommendation decision
Unique per response. Signals about what was shown reference it.
1The same value as the X-Request-ID response header.
1111The storefront moment that asks for recommendations. Three moments start from a product the shopper is looking at or just added (the shooter, context_item_id): pdp (product page), cart (right after adding to the cart) and checkout (when the purchase starts). The other three read only the cart: success-page (purchase finished), in-checkout (inside the checkout) and carousel (the cart page).
pdp, cart, checkout, success-page, in-checkout, carousel 1What the decision was taken from, echoed so the storefront does not have to remember it.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
1Pseudonymous identity of the browser that asks. The storefront SDK creates and keeps it; it carries no personal data and must never be an email, a phone number or a platform customer id. Sending it is optional, and a visitor that does not match this shape never fails the request: the server drops it, answers without it and does not store it.
Show child attributes
Show child attributes