Create a sandbox dynamic-pricing rule
Creates a dynamic-pricing rule in your sandbox, so /v1/prices/* returns a rule-adjusted
price you can build against.
Pricing rules are environment-scoped: a test key resolves only the rules you seed, and a live key only the merchant’s real ones. Rules are otherwise created by the merchant in their admin, which always writes production, so this is how a rule comes to exist in your sandbox.
Every field is optional; the defaults create an active rule taking 10% off every product,
starting today and running for 30 days. A rule scoped with applies_to other than all
requires target_ids, since a scoped rule with no targets matches nothing.
The environment is set by Galactic Core and is never read from the request body. Seeding also refreshes your sandbox pricing cache, so the new rule takes effect on the next request rather than when the cache expires.
Requires a secret test key (tybrite_sk_test_*).
curl --request POST \
--url https://api.tybritelabs.com/v1/sandbox/seed/pricing-rule \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Sandbox half price",
"rule_type": "percentage",
"discount_value": 50
}
'import requests
url = "https://api.tybritelabs.com/v1/sandbox/seed/pricing-rule"
payload = {
"name": "Sandbox half price",
"rule_type": "percentage",
"discount_value": 50
}
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({name: 'Sandbox half price', rule_type: 'percentage', discount_value: 50})
};
fetch('https://api.tybritelabs.com/v1/sandbox/seed/pricing-rule', 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.tybritelabs.com/v1/sandbox/seed/pricing-rule",
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([
'name' => 'Sandbox half price',
'rule_type' => 'percentage',
'discount_value' => 50
]),
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.tybritelabs.com/v1/sandbox/seed/pricing-rule"
payload := strings.NewReader("{\n \"name\": \"Sandbox half price\",\n \"rule_type\": \"percentage\",\n \"discount_value\": 50\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.tybritelabs.com/v1/sandbox/seed/pricing-rule")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Sandbox half price\",\n \"rule_type\": \"percentage\",\n \"discount_value\": 50\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/sandbox/seed/pricing-rule")
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 \"name\": \"Sandbox half price\",\n \"rule_type\": \"percentage\",\n \"discount_value\": 50\n}"
response = http.request(request)
puts response.read_body{
"pricing_rule": {
"id": "61156d88-c51f-48ec-a44b-61d10d8b2992",
"name": "Sandbox half price",
"rule_type": "percentage",
"discount_value": 50,
"applies_to": "all",
"target_ids": [],
"priority": 0,
"start_date": "2026-09-07T00:00:00+00:00",
"end_date": "2026-10-07T00:00:00+00:00",
"is_active": true,
"environment": "sandbox"
}
}{
"error": {
"code": "invalid_request",
"message": "Invalid request parameters",
"details": "The 'email' field is required"
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid Authorization header"
}
}{
"error": {
"code": "forbidden",
"message": "This operation requires a secret key. Publishable keys cover catalogue reads and the actions a shopper takes for themselves."
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests for this API key. Please slow down and try again shortly.",
"remaining": 0,
"reset": 1706198400
}
}{
"error": {
"code": "server_error",
"message": "An unexpected error occurred"
}
}Authorizations
API Key Authentication
Use your API key in the Authorization header:
Authorization: Bearer tybrite_sk_live_YOUR_KEY
Key Types:
Secret Keys (Server-Side Only):
- Format:
tybrite_sk_live_*(production) ortybrite_sk_test_*(sandbox) - Full read/write access to all endpoints
- ⚠️ NEVER expose in client-side code or public repositories
- Required for: every write a shopper does not make for themselves, authentication, payment verification, AI recommendations
Publishable Keys (Client-Safe):
- Format:
tybrite_pk_live_*(production) ortybrite_pk_test_*(sandbox) - Catalogue reads, plus the actions a shopper takes for themselves
- ✅ Safe for client-side JavaScript, mobile apps, and public code
- Allowed for: browsing products, search, CMS content, pricing queries, cart and wishlist, reviews, storefront events, and the Agent API's quotes, cart drafts and checkout intents
Endpoint-Specific Requirements:
- Authentication endpoints (
/v1/auth/*): Secret key required - Payment verification (
POST /v1/payments/verify): Secret key required - AI Recommendations (
POST /v1/recommendations): Secret key required - Semantic Search (
POST /v1/search): Both key types allowed (read-only operation) - Shopper actions (cart, wishlist, reviews, storefront events, Agent API quotes, cart drafts and checkout intents): Both key types allowed
- All other write operations: Secret key required
- All read operations: Both key types allowed
Using a publishable key for restricted operations returns 403 Forbidden.
Body
Defaults to a generated Sandbox pricing rule … name.
percentage takes a share off, fixed_amount a flat amount, fixed_price sets
the price outright, and markup adds to it.
percentage, fixed_amount, fixed_price, markup Percentage points for percentage and markup, else an amount. Must be greater than zero.
all, category, product, collection Required and non-empty when applies_to is not all.
Lower runs first when several rules match.
Defaults to today. Cannot be in the past.
Defaults to 30 days from today.
Response
Sandbox pricing rule created.
A dynamic-pricing rule created in the sandbox. Only a test key resolves it, so it adjusts prices
on /v1/prices/* for your sandbox traffic and never for a real shopper.
Show child attributes
Show child attributes
curl --request POST \
--url https://api.tybritelabs.com/v1/sandbox/seed/pricing-rule \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Sandbox half price",
"rule_type": "percentage",
"discount_value": 50
}
'import requests
url = "https://api.tybritelabs.com/v1/sandbox/seed/pricing-rule"
payload = {
"name": "Sandbox half price",
"rule_type": "percentage",
"discount_value": 50
}
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({name: 'Sandbox half price', rule_type: 'percentage', discount_value: 50})
};
fetch('https://api.tybritelabs.com/v1/sandbox/seed/pricing-rule', 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.tybritelabs.com/v1/sandbox/seed/pricing-rule",
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([
'name' => 'Sandbox half price',
'rule_type' => 'percentage',
'discount_value' => 50
]),
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.tybritelabs.com/v1/sandbox/seed/pricing-rule"
payload := strings.NewReader("{\n \"name\": \"Sandbox half price\",\n \"rule_type\": \"percentage\",\n \"discount_value\": 50\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.tybritelabs.com/v1/sandbox/seed/pricing-rule")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Sandbox half price\",\n \"rule_type\": \"percentage\",\n \"discount_value\": 50\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/sandbox/seed/pricing-rule")
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 \"name\": \"Sandbox half price\",\n \"rule_type\": \"percentage\",\n \"discount_value\": 50\n}"
response = http.request(request)
puts response.read_body{
"pricing_rule": {
"id": "61156d88-c51f-48ec-a44b-61d10d8b2992",
"name": "Sandbox half price",
"rule_type": "percentage",
"discount_value": 50,
"applies_to": "all",
"target_ids": [],
"priority": 0,
"start_date": "2026-09-07T00:00:00+00:00",
"end_date": "2026-10-07T00:00:00+00:00",
"is_active": true,
"environment": "sandbox"
}
}{
"error": {
"code": "invalid_request",
"message": "Invalid request parameters",
"details": "The 'email' field is required"
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid Authorization header"
}
}{
"error": {
"code": "forbidden",
"message": "This operation requires a secret key. Publishable keys cover catalogue reads and the actions a shopper takes for themselves."
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests for this API key. Please slow down and try again shortly.",
"remaining": 0,
"reset": 1706198400
}
}{
"error": {
"code": "server_error",
"message": "An unexpected error occurred"
}
}
