From b2c
Consume SCAPI Admin APIs for backend integrations like inventory sync, order management, catalog updates, and customer data. Guides OAuth with Account Manager, admin scopes, and base URL patterns.
npx claudepluginhub salesforcecommercecloud/b2c-developer-tooling --plugin b2cThis skill uses the workspace's default tool permissions.
This skill guides you through consuming Admin APIs for backend integrations, data synchronization, and management operations. Admin APIs are designed for server-to-server integration, not storefront use.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
This skill guides you through consuming Admin APIs for backend integrations, data synchronization, and management operations. Admin APIs are designed for server-to-server integration, not storefront use.
Note: For shopper-facing APIs (products, baskets, checkout), see b2c-scapi-shopper. This skill focuses on admin/backend operations.
Admin APIs are designed for backend systems and integrations:
https://{shortCode}.api.commercecloud.salesforce.com/{apiFamily}/{apiName}/v1/organizations/{organizationId}/{resource}
Example:
https://kv7kzm78.api.commercecloud.salesforce.com/product/products/v1/organizations/f_ecom_zzte_053/products/25518823M
Note: Admin APIs typically don't require siteId parameter (unlike Shopper APIs).
Admin APIs use Account Manager OAuth with client credentials flow.
# Get admin token (uses clientId/clientSecret from dw.json)
b2c auth token
# Get token with specific scopes
b2c auth token --auth-scope sfcc.orders --auth-scope sfcc.products
# Get token as JSON (includes expiration)
b2c auth token --json
See b2c-config skill for configuration details.
curl "https://account.demandware.com/dwsso/oauth2/access_token" \
--request 'POST' \
--user "${CLIENT_ID}:${CLIENT_SECRET}" \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data "grant_type=client_credentials" \
--data-urlencode "scope=SALESFORCE_COMMERCE_API:${TENANT_ID} ${SCOPES}"
Example:
CLIENT_ID="your-client-id"
CLIENT_SECRET="your-client-secret"
TENANT_ID="zzte_053"
SCOPES="sfcc.orders sfcc.products"
TOKEN=$(curl -s "https://account.demandware.com/dwsso/oauth2/access_token" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=client_credentials" \
--data-urlencode "scope=SALESFORCE_COMMERCE_API:$TENANT_ID $SCOPES" \
| jq -r '.access_token')
Admin APIs require two types of scopes:
SALESFORCE_COMMERCE_API:{tenant_id} - grants access to the tenantsfcc.catalogs, sfcc.orders.rw, etc. - grants API accessscope=SALESFORCE_COMMERCE_API:zzte_053 sfcc.catalogs sfcc.products.rw
See OAuth Scopes Reference for the complete scope list.
client_secret_postJWTManage product catalog data.
// Get product
const product = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/product/products/v1/organizations/${orgId}/products/${productId}`,
{
headers: { 'Authorization': `Bearer ${adminToken}` }
}
).then(r => r.json());
// Update product
await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/product/products/v1/organizations/${orgId}/products/${productId}`,
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: { default: 'Updated Product Name' },
shortDescription: { default: 'New description' }
})
}
);
Required Scopes:
sfcc.productssfcc.products.rwManage catalog structure and assignments.
// List catalogs
const catalogs = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/product/catalogs/v1/organizations/${orgId}/catalogs`,
{
headers: { 'Authorization': `Bearer ${adminToken}` }
}
).then(r => r.json());
// Get catalog details
const catalog = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/product/catalogs/v1/organizations/${orgId}/catalogs/${catalogId}`,
{
headers: { 'Authorization': `Bearer ${adminToken}` }
}
).then(r => r.json());
Required Scopes:
sfcc.catalogssfcc.catalogs.rwRetrieve and manage orders.
// Get order by number
const order = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/checkout/orders/v1/organizations/${orgId}/orders/${orderNo}?siteId=${siteId}`,
{
headers: { 'Authorization': `Bearer ${adminToken}` }
}
).then(r => r.json());
// Update order status
await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/checkout/orders/v1/organizations/${orgId}/orders/${orderNo}?siteId=${siteId}`,
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
status: 'completed',
shippingStatus: 'shipped'
})
}
);
Required Scopes:
sfcc.orderssfcc.orders.rwManage product inventory.
// Get inventory for a product
const availability = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/inventory/availability/v1/organizations/${orgId}/availability-records/search`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
skus: ['SKU001', 'SKU002'],
locationIds: ['warehouse-1']
})
}
).then(r => r.json());
// Update inventory
await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/inventory/availability/v1/organizations/${orgId}/availability-records`,
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
records: [{
sku: 'SKU001',
locationId: 'warehouse-1',
onHand: 100,
effectiveDate: new Date().toISOString()
}]
})
}
);
Required Scopes:
sfcc.inventory.availabilitysfcc.inventory.availability.rwHigh-performance bulk inventory import. Use for 1000+ SKU updates.
Critical Requirements:
// Step 1: Initiate import
const importJob = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/inventory/impex/v1/organizations/${orgId}/availability-records/imports`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({})
}
).then(r => r.json());
// Step 2: Prepare newline-delimited JSON
const ndjsonData = inventoryRecords
.map(r => JSON.stringify({
recordId: r.recordId || crypto.randomUUID(),
sku: r.sku,
locationId: r.locationId,
onHand: r.quantity,
effectiveDate: new Date().toISOString()
}))
.join('\n');
// Step 3: Upload data to the uploadLink
await fetch(importJob.uploadLink, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: ndjsonData
});
// Step 4: Monitor status
const status = await fetch(importJob.importStatusLink, {
headers: { 'Authorization': `Bearer ${adminToken}` }
}).then(r => r.json());
Required Scope: sfcc.inventory.impex-inventory
Note: Inventory IMPEX logs don't appear in Log Center. Use correlation IDs and monitor import status directly.
See Integration Patterns Reference for bulk import best practices.
Manage customer data.
// Search customers
const customers = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/customer/customers/v1/organizations/${orgId}/customer-search?siteId=${siteId}`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: {
textQuery: { fields: ['email'], searchPhrase: 'john@example.com' }
}
})
}
).then(r => r.json());
Required Scopes:
sfcc.shopper-customerssfcc.shopper-customers.rwManage promotions and campaigns.
// Get promotion
const promotion = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/pricing/promotions/v1/organizations/${orgId}/promotions/${promotionId}?siteId=${siteId}`,
{
headers: { 'Authorization': `Bearer ${adminToken}` }
}
).then(r => r.json());
// Update promotion
await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/pricing/promotions/v1/organizations/${orgId}/promotions/${promotionId}?siteId=${siteId}`,
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
enabled: true,
startDate: '2024-06-01T00:00:00Z',
endDate: '2024-06-30T23:59:59Z'
})
}
);
Required Scopes:
sfcc.promotionssfcc.promotions.rwInclude correlation IDs for tracking requests across systems:
const correlationId = crypto.randomUUID();
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${adminToken}`,
'correlation-id': correlationId
}
});
console.log(`Request ${correlationId} completed`);
// Search Log Center: externalID:({correlationId})
Enable verbose logging for debugging:
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${adminToken}`,
'sfdc_verbose': 'true'
}
});
Check Log Center under scapi.verbose category.
Note: Some Admin APIs (CDN Zones, Inventory, Shopper Context) don't log to Log Center.
| Status | Meaning | Action |
|---|---|---|
| 400 | Bad Request | Check request body/parameters |
| 401 | Unauthorized | Token expired - get new token |
| 403 | Forbidden | Missing scope or tenant access |
| 404 | Not Found | Resource doesn't exist |
| 429 | Rate Limited | Implement backoff |
| 500 | Server Error | Retry with backoff |
| 504 | Timeout | Request took > 60 seconds |
Admin APIs have lower rate limits than Shopper APIs. For bulk operations: