Product API for Edge Delivery Services.
- Main:
https://api.adobecommerce.live - Next:
https://api-next.adobecommerce.live
Set some environment variables to make the curl examples easier to read:
export ORG="acme"
export SITE="main"
export KEY="<SITE_API_KEY>"- All modifying requests require an Authorization header:
Authorization: Bearer <SITE_API_KEY> - Send JSON with
Content-Type: application/json - Products are stored and accessed by their URL path (e.g.,
/products/blender-pro-500)
Products are retrieved by their path:
curl -sS \
-H "Authorization: Bearer $KEY" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/catalog/products/blender-pro-500.json"Example response body:
{
"sku": "sku-123",
"name": "Blender Pro 500",
"path": "/products/blender-pro-500",
"url": "https://www.example.com/products/blender-pro-500",
"images": [
{ "url": "./media_a1b2c3d4e5f6789012345678901234567890abcd.jpg", "label": "main", "filename": "blender-pro-500-front" }
]
}When a filename is provided on an image, the rendered media URL includes a human-readable segment: ./media_{hash}/blender-pro-500-front.jpg. If filename is omitted the URL remains ./media_{hash}.jpg.
Minimal payload with the most important properties. The URL path determines where the product is stored.
curl -sS -X PUT \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/catalog/products/test-product.json" \
--data-binary @- <<'JSON'
{
"sku": "test-sku",
"name": "Test Product",
"path": "/products/test-product",
"url": "https://www.example.com/products/test-product"
}
JSONNote: The path field in the JSON represents the product's canonical path (e.g., /products/test-product). The API endpoint path includes /catalog/ as part of the API structure (e.g., /catalog/products/test-product.json), but this prefix is not included in the product's path field.
curl -sS -X PUT \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/catalog/products/blender-pro-500.json" \
--data-binary @- <<'JSON'
{
"sku": "sku-123",
"path": "/products/blender-pro-500",
"description": "Long product description...",
"name": "Blender Pro 500",
"metaTitle": "Product Name | Brand",
"metaDescription": "Short SEO description...",
"gtin": "0123456789012",
"url": "https://www.example.com/products/product-url-key",
"brand": "ExampleBrand",
"availability": "InStock",
"price": {
"currency": "USD",
"regular": "129.99",
"final": "99.99"
},
"itemCondition": "NewCondition",
"metadata": {
"color": "black",
"size": "M"
},
"options": [
{
"id": "finish",
"label": "Finish",
"position": 1,
"values": [
{ "value": "Matte" },
{ "value": "Glossy" }
]
}
],
"aggregateRating": {
"ratingValue": "4.3",
"reviewCount": "12",
"bestRating": "5",
"worstRating": "1"
},
"specifications": "<ul><li>Spec A</li><li>Spec B</li></ul>",
"images": [
{
"url": "https://cdn.example.com/images/sku-123/main.jpg",
"label": "Blender Pro 500 front view",
"filename": "blender-pro-500-front",
"roles": ["small", "thumbnail"],
"video": "https://cdn.example.com/videos/sku-123/overview.mp4"
}
],
"variants": [
{
"sku": "sku-123-RED",
"name": "Product Name - Red",
"price": {
"currency": "USD",
"regular": "129.99",
"final": "99.99"
},
"url": "https://www.example.com/products/product-url-key?color=red",
"images": [
{ "url": "https://cdn.example.com/images/sku-123/red.jpg", "label": "red", "filename": "blender-pro-500-red" }
],
"gtin": "0123456789013",
"description": "Red variant description",
"availability": "InStock",
"options": [ { "value": "Red", "id": "color", "uid": "opt-1" } ],
"itemCondition": "NewCondition",
"custom": { "material": "aluminum" }
}
],
"jsonld": "{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Product\",\n \"name\": \"Product Name\"\n}",
"custom": {
"warranty": "2 years",
"countryOfOrigin": "USA"
}
}
JSONSend up to 50 products at once by POSTing to the wildcard path. Each product must include a path field.
curl -sS -X POST \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/catalog/*" \
--data-binary @- <<'JSON'
[
{
"sku": "bulk-001",
"name": "Bulk Product 1",
"path": "/products/bulk-product-1",
"url": "https://www.example.com/products/bulk-product-1"
},
{
"sku": "bulk-002",
"name": "Bulk Product 2",
"path": "/products/bulk-product-2",
"url": "https://www.example.com/products/bulk-product-2"
}
]
JSONNotes:
- Bulk POST must target
catalog/*and will return 400 if the body is not an array or contains more than 50 items. - Each product in the array must include a valid
pathfield that follows the pattern/[a-z0-9-/]+. - Successful PUT/POST responses return 201 and include the saved product(s).
- If many products or images are included in a single bulk POST, the images will be processed asynchronously. Until they complete processing, the product-bus entry will continue to point to the URL provided in the POST.
Delete a product by its path:
curl -sS -X DELETE \
-H "Authorization: Bearer $KEY" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/catalog/products/blender-pro-500.json"Example response:
{
"message": "Product deleted successfully"
}NOTE: This API is deprecated and will be removed. Use the
/auth/service_tokenAPI instead.
Base URL structure: https://<host>/{org}/sites/{site}/auth/token
All auth routes require Authorization: Bearer <SITE_API_KEY> (or a superuser key).
curl -sS \
-H "Authorization: Bearer $KEY" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/auth/token"Example response body:
{ "token": "CURRENT_TOKEN_VALUE" }Generates a new token. Do not include a token in the request body.
curl -sS -X POST \
-H "Authorization: Bearer $KEY" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/auth/token"Example response body:
{ "token": "NEW_ROTATED_TOKEN" }Explicitly sets the token value.
curl -sS -X PUT \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/auth/token" \
--data-binary '{"token":"SPECIFIC_TOKEN_VALUE"}'Example response body:
{ "token": "SPECIFIC_TOKEN_VALUE" }JWT-based service tokens provide fine-grained, time-limited access for external services. Unlike legacy UUID tokens (which inherit a fixed service role), service tokens carry only the permissions explicitly granted at creation time.
Admins create service tokens via the /auth/service_token endpoint. The permissions allowlist is: catalog:read, catalog:write, orders:read, orders:write, index:read, index:write, customers:read, customers:write, emails:send. Permissions like admins:write, service_token:create, or config:write cannot be delegated to service tokens.
Requires admin auth (cookie or bearer token from OTP login).
curl -sS -X POST \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/auth/service_token" \
--data-binary @- <<'JSON'
{
"permissions": [
"emails:send",
"emails:send:*@example.com",
"emails:send:alerts@ops.internal"
],
"ttl": 2592000
}
JSONpermissions— Array of permissions. Email scope patterns use the prefixemails:send:followed by an exact address or*@domain.ttl— Token lifetime in seconds (max 1 year / 31,536,000 seconds).
Example response (201):
{ "token": "eyJhbG...", "ttl": 2592000 }curl -sS -X POST \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/auth/service_token/revoke" \
--data-binary '{"token":"eyJhbG..."}'Returns 204 on success. Revoked tokens are stored in {org}/{site}/revoked/service_tokens/ and checked on every request.
The /emails endpoint lets service tokens send transactional email via AWS SES. Access requires the emails:send permission plus one or more emails:send:<pattern> scopes defining which destination addresses are allowed.
The "from" address is read from the site config's otpEmailSender field (falling back to the FROM_EMAIL env var, then noreply@adobecommerce.live). Set it with:
curl -sS -X POST \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/config" \
--data-binary @- <<'JSON'
{
"otpEmailSender": "notifications@yourstore.com"
}
JSONThe sender must be a verified identity in your AWS SES account.
curl -sS -X POST \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/auth/service_token" \
--data-binary @- <<'JSON'
{
"permissions": [
"emails:send",
"emails:send:*@example.com",
"emails:send:vip@partner.org"
],
"ttl": 86400
}
JSONThis token can email any @example.com address and vip@partner.org, but no others. Save the returned token value.
export SERVICE_TOKEN="eyJhbG..."
curl -sS -X POST \
-H "Authorization: Bearer $SERVICE_TOKEN" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/emails" \
--data-binary @- <<'JSON'
{
"toEmail": "subscriber@example.com",
"subject": "Welcome to our newsletter",
"html": "<h1>Welcome!</h1><p>Thanks for subscribing.</p>",
"cc": ["team@example.com"],
"bcc": ["archive@example.com"]
}
JSONtoEmail—stringorstring[]. Required.subject—string. Required.html—string(max 256 KB). Required.cc—string[]. Optional.bcc—string[]. Optional.- Total recipients across all fields is capped at 50.
All addresses in toEmail, cc, and bcc are checked against the token's email scopes.
Example response (200):
{ "success": true }The /secrets endpoint stores encrypted configuration for third-party integrations (e.g., payment provider credentials). Secrets are write-only via the API, encrypted at rest with per-tenant derived keys (HKDF + AES-GCM-256), and readable only by internal service code via StorageClient.getSecrets().
- Only admins can write secrets. The
secrets:writepermission cannot be granted to service tokens. - Only known secret store IDs are accepted (see
src/schemas/secrets/index.jsfor the lookup table). - Secrets can be stored at a root path (site-wide default) or a locale-specific path. When read internally, locale secrets override root secrets.
curl -sS -X PUT \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/secrets/payments-chase.json" \
--data-binary @- <<'JSON'
{
"merchantId": "merchant-123",
"apiKey": "key-abc",
"apiSecret": "secret-xyz",
"environment": "production"
}
JSONReturns 204 on success. The secret is encrypted and stored at SECRETS_BUCKET:{org}/{site}/secrets/payments-chase.json.
curl -sS -X PUT \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"https://api.adobecommerce.live/$ORG/sites/$SITE/secrets/ca/en/payments-chase.json" \
--data-binary @- <<'JSON'
{
"merchantId": "ca-merchant-456",
"apiKey": "ca-key-def",
"apiSecret": "ca-secret-uvw",
"environment": "production"
}
JSONWhen code calls StorageClient.getSecrets('/ca/en/payments-chase.json'), both the root and locale secrets are fetched and merged, with locale values taking precedence.
| Property | Type | Description |
|---|---|---|
sku |
string |
Unique stock keeping unit. Required. |
path |
string |
URL path where the product is accessible (e.g., /products/blender-pro-500). Must match pattern /[a-z0-9]+(-[a-z0-9]+)*(\/[a-z0-9]+(-[a-z0-9]+)*)*. Required. |
description |
string |
Long description, free text or HTML. |
name |
string |
Human-readable product name. Required. |
metaTitle |
string |
SEO title. |
metaDescription |
string |
SEO description. |
gtin |
string |
Global Trade Item Number. |
url |
string |
Canonical product URL on the origin site. |
brand |
string |
Brand name. |
availability |
SchemaOrgAvailability |
Product availability status. |
price |
ProductBusPrice |
Pricing information for the product. |
itemCondition |
SchemaOrgItemCondition |
Condition of the item. |
metadata |
Record<string,string> |
Arbitrary string metadata map. |
options |
ProductBusOption[] |
Configurable options presented on PDP. |
aggregateRating |
AggregateRating |
Structured rating information. |
specifications |
string |
Structured specs (e.g., HTML snippet). |
images |
ProductBusMedia[] |
Media gallery. |
variants |
ProductBusVariant[] |
Variant entries for configurable products. |
jsonld |
string |
Product JSON-LD blob (max 128,000 chars). Intended for Schema.org markup. |
custom |
CustomObject |
Arbitrary custom data bag (not indexed by default). |
| Property | Type | Description |
|---|---|---|
currency |
string |
ISO currency code for the price values. |
regular |
string |
Regular price amount as a string. |
final |
string |
Final/sale price amount as a string. |
| Property | Type | Description |
|---|---|---|
url |
string |
Absolute or relative media URL. Required. |
label |
string |
Optional label or alt text. |
filename |
string |
Optional human-readable filename segment inserted into the media URL after processing. Only letters, digits, hyphens, and underscores are allowed (no dots, slashes, or spaces). E.g. blender-pro-500-front produces ./media_{hash}/blender-pro-500-front.jpg. Omitting this field leaves the URL as ./media_{hash}.jpg. |
roles |
string[] |
Optional role hints (e.g., thumbnail, small). |
video |
string |
Optional related video URL. |
| Property | Type | Description |
|---|---|---|
id |
string |
Optional value identifier. |
value |
string |
Display value. Required. |
uid |
string |
Optional stable unique identifier. |
| Property | Type | Description |
|---|---|---|
id |
string |
Optional option identifier. |
label |
string |
Display label for the option. Required. |
position |
number |
Display ordering hint. |
values |
ProductBusOptionValue[] |
List of selectable values. Required. |
| Property | Type | Description |
|---|---|---|
sku |
string |
Variant SKU. Required. |
name |
string |
Variant display name. Required. |
price |
ProductBusPrice |
Variant pricing. |
url |
string |
Variant URL. Required. |
images |
ProductBusMedia[] |
Variant media gallery. Required. |
gtin |
string |
Variant GTIN. |
description |
string |
Variant description. |
availability |
SchemaOrgAvailability |
Variant availability. |
options |
ProductBusOptionValue[] |
Selected option values for this variant. |
itemCondition |
SchemaOrgItemCondition |
Variant condition. |
custom |
CustomObject |
Arbitrary custom data for the variant. |
| Property | Type | Description |
|---|---|---|
ratingValue |
string |
Average rating value. |
reviewCount |
string |
Number of reviews (string-encoded integer). |
bestRating |
string |
Maximum possible rating. |
worstRating |
string |
Minimum possible rating. |
| Property | Type | Description |
|---|---|---|
availability |
enum |
One of: BackOrder, Discontinued, InStock, InStoreOnly, LimitedAvailability, MadeToOrder, OnlineOnly, OutOfStock, PreOrder, PreSale, Reserved, SoldOut. |
| Property | Type | Description |
|---|---|---|
itemCondition |
enum |
One of: DamagedCondition, NewCondition, RefurbishedCondition, UsedCondition. |
| Property | Type | Description |
|---|---|---|
* |
any |
Arbitrary key-value pairs. Additional properties allowed. |