Ingest a batch of products
Push or sync a batch of products into your store from an external source. Accepts
JSON, XML, or CSV — declare the format with the Content-Type header
(application/json, application/xml, text/csv) or the ?format= query parameter.
Batch size. A request carries at most 12 products; a larger batch is rejected with
400 rather than applied in part. Send a large catalog as a sequence of batches, or
configure a scheduled feed pull, which is built for whole-catalog sync.
Upsert by SKU. A product whose sku already exists in your store is updated;
a new sku is created. Pass ?strategy=create_only to skip existing SKUs instead
of updating them.
Variants. Rows that share the same product_group value become variants of one
product (each row needs its own unique sku). Rows without a product_group are
single-variant products.
Partial success. Rows are validated and applied independently — one bad row never
fails the whole batch. The response always carries a summary with created / updated /
skipped / failed counts and an errors array describing every rejected row (its
position, SKU, the offending field, and a human-readable reason). If every row
fails validation the response status is 422.
Required headers (same signing scheme as orders and payments):
Idempotency-Key— a unique key per batch; retrying with the same key returns the original result instead of re-processing.X-Timestamp— unix time in seconds, within 5 minutes of server time.X-Signature— base64 HMAC-SHA256 of`${X-Timestamp}.${raw_body}`signed with your store’s signing secret (the Integrations page, Developer section).
Tip: validate your feed first with POST /v1/ingest/test (no key, no writes).
curl --request POST \
--url https://api.tybritelabs.com/v1/ingest/products \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-Signature: <x-signature>' \
--header 'X-Timestamp: <x-timestamp>' \
--data '
{
"products": [
{
"sku": "LAMP-01",
"name": "Aurora LED Desk Lamp",
"category": "Home",
"brand": "Lumio",
"price": 36.9,
"cost_price": 17.2,
"stock": 40,
"threshold": 5
},
{
"sku": "TEE-BLK-S",
"product_group": "TEE-CLASSIC",
"name": "Classic Cotton Tee",
"variant_name": "Black / S",
"category": "Apparel",
"price": 22,
"stock": 30
},
{
"sku": "TEE-BLK-M",
"product_group": "TEE-CLASSIC",
"name": "Classic Cotton Tee",
"variant_name": "Black / M",
"category": "Apparel",
"price": 22,
"stock": 25
}
]
}
'import requests
url = "https://api.tybritelabs.com/v1/ingest/products"
payload = { "products": [
{
"sku": "LAMP-01",
"name": "Aurora LED Desk Lamp",
"category": "Home",
"brand": "Lumio",
"price": 36.9,
"cost_price": 17.2,
"stock": 40,
"threshold": 5
},
{
"sku": "TEE-BLK-S",
"product_group": "TEE-CLASSIC",
"name": "Classic Cotton Tee",
"variant_name": "Black / S",
"category": "Apparel",
"price": 22,
"stock": 30
},
{
"sku": "TEE-BLK-M",
"product_group": "TEE-CLASSIC",
"name": "Classic Cotton Tee",
"variant_name": "Black / M",
"category": "Apparel",
"price": 22,
"stock": 25
}
] }
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-Timestamp": "<x-timestamp>",
"X-Signature": "<x-signature>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-Timestamp': '<x-timestamp>',
'X-Signature': '<x-signature>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
products: [
{
sku: 'LAMP-01',
name: 'Aurora LED Desk Lamp',
category: 'Home',
brand: 'Lumio',
price: 36.9,
cost_price: 17.2,
stock: 40,
threshold: 5
},
{
sku: 'TEE-BLK-S',
product_group: 'TEE-CLASSIC',
name: 'Classic Cotton Tee',
variant_name: 'Black / S',
category: 'Apparel',
price: 22,
stock: 30
},
{
sku: 'TEE-BLK-M',
product_group: 'TEE-CLASSIC',
name: 'Classic Cotton Tee',
variant_name: 'Black / M',
category: 'Apparel',
price: 22,
stock: 25
}
]
})
};
fetch('https://api.tybritelabs.com/v1/ingest/products', 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/ingest/products",
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([
'products' => [
[
'sku' => 'LAMP-01',
'name' => 'Aurora LED Desk Lamp',
'category' => 'Home',
'brand' => 'Lumio',
'price' => 36.9,
'cost_price' => 17.2,
'stock' => 40,
'threshold' => 5
],
[
'sku' => 'TEE-BLK-S',
'product_group' => 'TEE-CLASSIC',
'name' => 'Classic Cotton Tee',
'variant_name' => 'Black / S',
'category' => 'Apparel',
'price' => 22,
'stock' => 30
],
[
'sku' => 'TEE-BLK-M',
'product_group' => 'TEE-CLASSIC',
'name' => 'Classic Cotton Tee',
'variant_name' => 'Black / M',
'category' => 'Apparel',
'price' => 22,
'stock' => 25
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>",
"X-Signature: <x-signature>",
"X-Timestamp: <x-timestamp>"
],
]);
$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/ingest/products"
payload := strings.NewReader("{\n \"products\": [\n {\n \"sku\": \"LAMP-01\",\n \"name\": \"Aurora LED Desk Lamp\",\n \"category\": \"Home\",\n \"brand\": \"Lumio\",\n \"price\": 36.9,\n \"cost_price\": 17.2,\n \"stock\": 40,\n \"threshold\": 5\n },\n {\n \"sku\": \"TEE-BLK-S\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / S\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 30\n },\n {\n \"sku\": \"TEE-BLK-M\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / M\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 25\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-Timestamp", "<x-timestamp>")
req.Header.Add("X-Signature", "<x-signature>")
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/ingest/products")
.header("Idempotency-Key", "<idempotency-key>")
.header("X-Timestamp", "<x-timestamp>")
.header("X-Signature", "<x-signature>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"products\": [\n {\n \"sku\": \"LAMP-01\",\n \"name\": \"Aurora LED Desk Lamp\",\n \"category\": \"Home\",\n \"brand\": \"Lumio\",\n \"price\": 36.9,\n \"cost_price\": 17.2,\n \"stock\": 40,\n \"threshold\": 5\n },\n {\n \"sku\": \"TEE-BLK-S\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / S\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 30\n },\n {\n \"sku\": \"TEE-BLK-M\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / M\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 25\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/ingest/products")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-Timestamp"] = '<x-timestamp>'
request["X-Signature"] = '<x-signature>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"products\": [\n {\n \"sku\": \"LAMP-01\",\n \"name\": \"Aurora LED Desk Lamp\",\n \"category\": \"Home\",\n \"brand\": \"Lumio\",\n \"price\": 36.9,\n \"cost_price\": 17.2,\n \"stock\": 40,\n \"threshold\": 5\n },\n {\n \"sku\": \"TEE-BLK-S\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / S\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 30\n },\n {\n \"sku\": \"TEE-BLK-M\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / M\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 25\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"status": "partial",
"format": "json",
"strategy": "upsert_by_sku",
"summary": {
"rows_total": 15,
"rows_created": 9,
"rows_updated": 1,
"rows_skipped": 1,
"rows_failed": 4
},
"errors": [
{
"row": 3,
"sku": "TEE-RED-S",
"field": "price",
"reason": "price must be a positive number"
}
]
}{
"error": {
"code": "invalid_request",
"message": "Invalid request parameters",
"details": "The 'email' field is required"
}
}{
"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": "forbidden",
"message": "This operation requires a secret key. Publishable keys cover catalogue reads and the actions a shopper takes for themselves."
}
}{
"error": {
"code": "conflict",
"message": "A customer with this email already exists for this store"
}
}{
"status": "success",
"format": "json",
"strategy": "upsert_by_sku",
"summary": {
"rows_total": 123,
"rows_created": 123,
"rows_updated": 123,
"rows_skipped": 123,
"rows_failed": 123
},
"errors": [
{
"row": 3,
"sku": "TEE-RED-S",
"field": "price",
"reason": "price must be a positive number"
}
]
}{
"error": {
"code": "rate_limited",
"message": "Too many requests for this API key. Please slow down and try again shortly.",
"remaining": 0,
"reset": 1706198400
}
}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.
Headers
Unique key per batch; retrying with the same key returns the original result instead of re-importing.
Unix timestamp in seconds (current time). Must be within 5 minutes of server time. Used to prevent replay attacks.
Base64-encoded HMAC-SHA256 of the payload (${X-Timestamp}.${raw_body}), signed with your
HMAC secret from the Integrations page (Developer section). Required in addition to the secret key.
Query Parameters
Overrides the Content-Type for format detection.
json, xml, csv upsert_by_sku (default) updates existing SKUs; create_only skips them.
upsert_by_sku, create_only When true, validate and report without writing anything.
Body
A batch of products. For JSON use { "products": [ … ] } (or a bare array). For
CSV, the first row is a header; for XML, a <products> root with <product>
children. Field names are matched leniently (e.g. Product Name → name).
Show child attributes
Show child attributes
Response
Batch processed. May be a full success or a partial success — inspect summary
and errors. status is success (no failures) or partial (some rows failed).
The outcome of an ingestion batch.
success (no failures), partial (some rows failed, the rest applied), or
failed (every row failed; nothing written).
success, partial, failed json, xml, csv upsert_by_sku, create_only Per-batch counts.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
curl --request POST \
--url https://api.tybritelabs.com/v1/ingest/products \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-Signature: <x-signature>' \
--header 'X-Timestamp: <x-timestamp>' \
--data '
{
"products": [
{
"sku": "LAMP-01",
"name": "Aurora LED Desk Lamp",
"category": "Home",
"brand": "Lumio",
"price": 36.9,
"cost_price": 17.2,
"stock": 40,
"threshold": 5
},
{
"sku": "TEE-BLK-S",
"product_group": "TEE-CLASSIC",
"name": "Classic Cotton Tee",
"variant_name": "Black / S",
"category": "Apparel",
"price": 22,
"stock": 30
},
{
"sku": "TEE-BLK-M",
"product_group": "TEE-CLASSIC",
"name": "Classic Cotton Tee",
"variant_name": "Black / M",
"category": "Apparel",
"price": 22,
"stock": 25
}
]
}
'import requests
url = "https://api.tybritelabs.com/v1/ingest/products"
payload = { "products": [
{
"sku": "LAMP-01",
"name": "Aurora LED Desk Lamp",
"category": "Home",
"brand": "Lumio",
"price": 36.9,
"cost_price": 17.2,
"stock": 40,
"threshold": 5
},
{
"sku": "TEE-BLK-S",
"product_group": "TEE-CLASSIC",
"name": "Classic Cotton Tee",
"variant_name": "Black / S",
"category": "Apparel",
"price": 22,
"stock": 30
},
{
"sku": "TEE-BLK-M",
"product_group": "TEE-CLASSIC",
"name": "Classic Cotton Tee",
"variant_name": "Black / M",
"category": "Apparel",
"price": 22,
"stock": 25
}
] }
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-Timestamp": "<x-timestamp>",
"X-Signature": "<x-signature>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-Timestamp': '<x-timestamp>',
'X-Signature': '<x-signature>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
products: [
{
sku: 'LAMP-01',
name: 'Aurora LED Desk Lamp',
category: 'Home',
brand: 'Lumio',
price: 36.9,
cost_price: 17.2,
stock: 40,
threshold: 5
},
{
sku: 'TEE-BLK-S',
product_group: 'TEE-CLASSIC',
name: 'Classic Cotton Tee',
variant_name: 'Black / S',
category: 'Apparel',
price: 22,
stock: 30
},
{
sku: 'TEE-BLK-M',
product_group: 'TEE-CLASSIC',
name: 'Classic Cotton Tee',
variant_name: 'Black / M',
category: 'Apparel',
price: 22,
stock: 25
}
]
})
};
fetch('https://api.tybritelabs.com/v1/ingest/products', 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/ingest/products",
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([
'products' => [
[
'sku' => 'LAMP-01',
'name' => 'Aurora LED Desk Lamp',
'category' => 'Home',
'brand' => 'Lumio',
'price' => 36.9,
'cost_price' => 17.2,
'stock' => 40,
'threshold' => 5
],
[
'sku' => 'TEE-BLK-S',
'product_group' => 'TEE-CLASSIC',
'name' => 'Classic Cotton Tee',
'variant_name' => 'Black / S',
'category' => 'Apparel',
'price' => 22,
'stock' => 30
],
[
'sku' => 'TEE-BLK-M',
'product_group' => 'TEE-CLASSIC',
'name' => 'Classic Cotton Tee',
'variant_name' => 'Black / M',
'category' => 'Apparel',
'price' => 22,
'stock' => 25
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>",
"X-Signature: <x-signature>",
"X-Timestamp: <x-timestamp>"
],
]);
$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/ingest/products"
payload := strings.NewReader("{\n \"products\": [\n {\n \"sku\": \"LAMP-01\",\n \"name\": \"Aurora LED Desk Lamp\",\n \"category\": \"Home\",\n \"brand\": \"Lumio\",\n \"price\": 36.9,\n \"cost_price\": 17.2,\n \"stock\": 40,\n \"threshold\": 5\n },\n {\n \"sku\": \"TEE-BLK-S\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / S\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 30\n },\n {\n \"sku\": \"TEE-BLK-M\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / M\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 25\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-Timestamp", "<x-timestamp>")
req.Header.Add("X-Signature", "<x-signature>")
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/ingest/products")
.header("Idempotency-Key", "<idempotency-key>")
.header("X-Timestamp", "<x-timestamp>")
.header("X-Signature", "<x-signature>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"products\": [\n {\n \"sku\": \"LAMP-01\",\n \"name\": \"Aurora LED Desk Lamp\",\n \"category\": \"Home\",\n \"brand\": \"Lumio\",\n \"price\": 36.9,\n \"cost_price\": 17.2,\n \"stock\": 40,\n \"threshold\": 5\n },\n {\n \"sku\": \"TEE-BLK-S\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / S\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 30\n },\n {\n \"sku\": \"TEE-BLK-M\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / M\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 25\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/ingest/products")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-Timestamp"] = '<x-timestamp>'
request["X-Signature"] = '<x-signature>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"products\": [\n {\n \"sku\": \"LAMP-01\",\n \"name\": \"Aurora LED Desk Lamp\",\n \"category\": \"Home\",\n \"brand\": \"Lumio\",\n \"price\": 36.9,\n \"cost_price\": 17.2,\n \"stock\": 40,\n \"threshold\": 5\n },\n {\n \"sku\": \"TEE-BLK-S\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / S\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 30\n },\n {\n \"sku\": \"TEE-BLK-M\",\n \"product_group\": \"TEE-CLASSIC\",\n \"name\": \"Classic Cotton Tee\",\n \"variant_name\": \"Black / M\",\n \"category\": \"Apparel\",\n \"price\": 22,\n \"stock\": 25\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"status": "partial",
"format": "json",
"strategy": "upsert_by_sku",
"summary": {
"rows_total": 15,
"rows_created": 9,
"rows_updated": 1,
"rows_skipped": 1,
"rows_failed": 4
},
"errors": [
{
"row": 3,
"sku": "TEE-RED-S",
"field": "price",
"reason": "price must be a positive number"
}
]
}{
"error": {
"code": "invalid_request",
"message": "Invalid request parameters",
"details": "The 'email' field is required"
}
}{
"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": "forbidden",
"message": "This operation requires a secret key. Publishable keys cover catalogue reads and the actions a shopper takes for themselves."
}
}{
"error": {
"code": "conflict",
"message": "A customer with this email already exists for this store"
}
}{
"status": "success",
"format": "json",
"strategy": "upsert_by_sku",
"summary": {
"rows_total": 123,
"rows_created": 123,
"rows_updated": 123,
"rows_skipped": 123,
"rows_failed": 123
},
"errors": [
{
"row": 3,
"sku": "TEE-RED-S",
"field": "price",
"reason": "price must be a positive number"
}
]
}{
"error": {
"code": "rate_limited",
"message": "Too many requests for this API key. Please slow down and try again shortly.",
"remaining": 0,
"reset": 1706198400
}
}
