Endpoint
POST /api/workspace/{workspaceId}/catalogs/{catalogId}/batch/silver
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Your workspace ID |
catalogId | string | Yes | The catalog to process |
Request body
{
"productIds": ["prod_abc", "prod_def"],
"scope": "selection"
}
| Field | Type | Required | Description |
|---|---|---|---|
productIds | string[] | No | Product IDs to process. Required when scope is "selection" |
scope | string | Yes | "selection" or "all". When "all", productIds is ignored |
Response
{
"results": [
{
"productId": "prod_abc",
"status": "success",
"fieldsNormalized": 4,
"duplicateOf": null,
"urlsValidated": 3
},
{
"productId": "prod_def",
"status": "success",
"fieldsNormalized": 2,
"duplicateOf": "prod_xyz",
"urlsValidated": 1
},
{
"productId": "prod_ghi",
"status": "error",
"error": "Brand not found: 'AcmeCorp'"
}
],
"processed": 3,
"duration_ms": 1240
}
SilverResult fields
| Field | Type | Description |
|---|---|---|
productId | string | The product that was processed |
status | string | "success" or "error" |
fieldsNormalized | number | Count of fields that were transformed |
duplicateOf | string | null | If a duplicate was detected, the ID of the canonical product |
urlsValidated | number | Count of image/media URLs checked for HTTP 200 |
error | string | Present only when status is "error" |
Top-level response fields
| Field | Type | Description |
|---|---|---|
results | SilverResult[] | Per-product results |
processed | number | Total products processed (success + error) |
duration_ms | number | Total processing time in milliseconds |
Examples
# Normalize a selection of products
curl -X POST "https://app.alana.shopping/api/workspace/ws_123/catalogs/cat_456/batch/silver" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"productIds": ["prod_abc", "prod_def", "prod_ghi"],
"scope": "selection"
}'
const workspaceId = 'ws_123';
const catalogId = 'cat_456';
const response = await fetch(
`https://app.alana.shopping/api/workspace/${workspaceId}/catalogs/${catalogId}/batch/silver`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ALANA_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
productIds: ['prod_abc', 'prod_def', 'prod_ghi'],
scope: 'selection',
}),
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
const { results, processed, duration_ms } = await response.json();
console.log(`Processed ${processed} products in ${duration_ms}ms`);
const duplicates = results.filter(r => r.duplicateOf);
if (duplicates.length > 0) {
console.log(`Found ${duplicates.length} duplicates`);
}
import requests
import os
workspace_id = "ws_123"
catalog_id = "cat_456"
response = requests.post(
f"https://app.alana.shopping/api/workspace/{workspace_id}/catalogs/{catalog_id}/batch/silver",
headers={
"Authorization": f"Bearer {os.environ['ALANA_API_KEY']}",
"Content-Type": "application/json",
},
json={
"productIds": ["prod_abc", "prod_def", "prod_ghi"],
"scope": "selection",
}
)
response.raise_for_status()
data = response.json()
print(f"Processed {data['processed']} products in {data['duration_ms']}ms")
errors = [r for r in data["results"] if r["status"] == "error"]
if errors:
for e in errors:
print(f"Error on {e['productId']}: {e['error']}")
Normalize entire catalog
curl -X POST "https://app.alana.shopping/api/workspace/ws_123/catalogs/cat_456/batch/silver" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"scope": "all"}'
const response = await fetch(
`https://app.alana.shopping/api/workspace/${workspaceId}/catalogs/${catalogId}/batch/silver`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ALANA_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ scope: 'all' }),
}
);
const result = await response.json();
console.log(`Normalized ${result.processed} products`);
import requests, os
response = requests.post(
f"https://app.alana.shopping/api/workspace/{workspace_id}/catalogs/{catalog_id}/batch/silver",
headers={"Authorization": f"Bearer {os.environ['ALANA_API_KEY']}"},
json={"scope": "all"}
)
data = response.json()
print(f"Normalized {data['processed']} products in {data['duration_ms']}ms")
Error responses
| HTTP status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | scope is missing or invalid |
| 403 | INSUFFICIENT_PERMISSIONS | API key lacks catalogs:write |
| 404 | CATALOG_NOT_FOUND | Catalog does not exist in workspace |
| 409 | JOB_ALREADY_RUNNING | A Silver or Gold job is already in progress |
| 429 | RATE_LIMIT_EXCEEDED | Slow down and retry after the Retry-After header value |