Create a sandbox B2B buyer account
Creates a B2B buyer account in your sandbox, which is what makes the /v1/b2b/* endpoints
reachable with a test key.
Every B2B endpoint resolves a buyer account for the calling customer before it does anything
else, and returns 403 when there isn’t one. Buyer accounts are otherwise created by the
merchant in their admin, which always writes production — so without this, a test key is
refused across the whole B2B surface.
Pass the customer_id of a customer you created with a test key. A production customer is
refused, so a sandbox buyer account can never attach to one of the merchant’s real customers.
A store still has to have B2B enabled: if it does not, every B2B endpoint keeps returning
404, and seeding a buyer account does not change that.
Requires a secret test key (tybrite_sk_test_*).
curl --request POST \
--url https://api.tybritelabs.com/v1/sandbox/seed/b2b-buyer-account \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "92a2fe11-2a7f-46e4-acf0-541b5e77828a",
"payment_terms": "net30",
"credit_limit": 5000
}
'import requests
url = "https://api.tybritelabs.com/v1/sandbox/seed/b2b-buyer-account"
payload = {
"customer_id": "92a2fe11-2a7f-46e4-acf0-541b5e77828a",
"payment_terms": "net30",
"credit_limit": 5000
}
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({
customer_id: '92a2fe11-2a7f-46e4-acf0-541b5e77828a',
payment_terms: 'net30',
credit_limit: 5000
})
};
fetch('https://api.tybritelabs.com/v1/sandbox/seed/b2b-buyer-account', 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/b2b-buyer-account",
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([
'customer_id' => '92a2fe11-2a7f-46e4-acf0-541b5e77828a',
'payment_terms' => 'net30',
'credit_limit' => 5000
]),
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/b2b-buyer-account"
payload := strings.NewReader("{\n \"customer_id\": \"92a2fe11-2a7f-46e4-acf0-541b5e77828a\",\n \"payment_terms\": \"net30\",\n \"credit_limit\": 5000\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/b2b-buyer-account")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customer_id\": \"92a2fe11-2a7f-46e4-acf0-541b5e77828a\",\n \"payment_terms\": \"net30\",\n \"credit_limit\": 5000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/sandbox/seed/b2b-buyer-account")
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 \"customer_id\": \"92a2fe11-2a7f-46e4-acf0-541b5e77828a\",\n \"payment_terms\": \"net30\",\n \"credit_limit\": 5000\n}"
response = http.request(request)
puts response.read_body{
"buyer_account": {
"id": "e23b79a8-1c9c-4594-b587-50bb0518e55a",
"customer_id": "92a2fe11-2a7f-46e4-acf0-541b5e77828a",
"payment_terms": "net30",
"credit_limit": 5000,
"credit_used": 0,
"tax_exempt": false,
"on_hold": false,
"checkout_policy": null,
"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": "invalid_request",
"message": "Missing required field",
"details": "The 'email' field is required",
"hint": "<string>",
"available_stock": 123,
"current_cart_quantity": 123,
"limit": 123,
"remaining": 123,
"reset": 123
}
}{
"error": {
"code": "invalid_request",
"message": "Missing required field",
"details": "The 'email' field is required",
"hint": "<string>",
"available_stock": 123,
"current_cart_quantity": 123,
"limit": 123,
"remaining": 123,
"reset": 123
}
}{
"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
A sandbox customer of your store. Must already exist.
prepaid, net15, net30, net60 Credit the buyer may draw on. Zero or greater.
How this buyer checks out. Left unset by default.
pay_now, terms, upfront_then_terms Response
Sandbox B2B buyer account created.
A B2B buyer account created in the sandbox. Its presence is what makes the /v1/b2b/* endpoints
reachable for that customer with a test key.
Show child attributes
Show child attributes
curl --request POST \
--url https://api.tybritelabs.com/v1/sandbox/seed/b2b-buyer-account \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "92a2fe11-2a7f-46e4-acf0-541b5e77828a",
"payment_terms": "net30",
"credit_limit": 5000
}
'import requests
url = "https://api.tybritelabs.com/v1/sandbox/seed/b2b-buyer-account"
payload = {
"customer_id": "92a2fe11-2a7f-46e4-acf0-541b5e77828a",
"payment_terms": "net30",
"credit_limit": 5000
}
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({
customer_id: '92a2fe11-2a7f-46e4-acf0-541b5e77828a',
payment_terms: 'net30',
credit_limit: 5000
})
};
fetch('https://api.tybritelabs.com/v1/sandbox/seed/b2b-buyer-account', 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/b2b-buyer-account",
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([
'customer_id' => '92a2fe11-2a7f-46e4-acf0-541b5e77828a',
'payment_terms' => 'net30',
'credit_limit' => 5000
]),
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/b2b-buyer-account"
payload := strings.NewReader("{\n \"customer_id\": \"92a2fe11-2a7f-46e4-acf0-541b5e77828a\",\n \"payment_terms\": \"net30\",\n \"credit_limit\": 5000\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/b2b-buyer-account")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customer_id\": \"92a2fe11-2a7f-46e4-acf0-541b5e77828a\",\n \"payment_terms\": \"net30\",\n \"credit_limit\": 5000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/sandbox/seed/b2b-buyer-account")
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 \"customer_id\": \"92a2fe11-2a7f-46e4-acf0-541b5e77828a\",\n \"payment_terms\": \"net30\",\n \"credit_limit\": 5000\n}"
response = http.request(request)
puts response.read_body{
"buyer_account": {
"id": "e23b79a8-1c9c-4594-b587-50bb0518e55a",
"customer_id": "92a2fe11-2a7f-46e4-acf0-541b5e77828a",
"payment_terms": "net30",
"credit_limit": 5000,
"credit_used": 0,
"tax_exempt": false,
"on_hold": false,
"checkout_policy": null,
"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": "invalid_request",
"message": "Missing required field",
"details": "The 'email' field is required",
"hint": "<string>",
"available_stock": 123,
"current_cart_quantity": 123,
"limit": 123,
"remaining": 123,
"reset": 123
}
}{
"error": {
"code": "invalid_request",
"message": "Missing required field",
"details": "The 'email' field is required",
"hint": "<string>",
"available_stock": 123,
"current_cart_quantity": 123,
"limit": 123,
"remaining": 123,
"reset": 123
}
}{
"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"
}
}
