Skip to content

adobe-rnd/helix-commerce-api

Repository files navigation

helix-commerce-api

Product API for Edge Delivery Services.

Environments

  • Main: https://api.adobecommerce.live
  • Next: https://api-next.adobecommerce.live

API

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)

GET a product

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.

PUT a product (small example)

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"
}
JSON

Note: 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.

PUT a product (complete example with all properties)

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"
  }
}
JSON

Bulk POST products

Send 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"
  }
]
JSON

Notes:

  • 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 path field 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

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"
}

Auth token management

NOTE: This API is deprecated and will be removed. Use the /auth/service_token API instead.

Base URL structure: https://<host>/{org}/sites/{site}/auth/token

All auth routes require Authorization: Bearer <SITE_API_KEY> (or a superuser key).

Fetch auth token (GET)

curl -sS \
  -H "Authorization: Bearer $KEY" \
  "https://api.adobecommerce.live/$ORG/sites/$SITE/auth/token"

Example response body:

{ "token": "CURRENT_TOKEN_VALUE" }

Rotate auth token (POST)

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" }

Set auth token (PUT)

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" }

Service tokens

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.

Create a service token (POST)

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
}
JSON
  • permissions — Array of permissions. Email scope patterns use the prefix emails: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 }

Revoke a service token (POST)

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.

Transactional emails

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.

Step 1: Configure the sender address

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"
}
JSON

The sender must be a verified identity in your AWS SES account.

Step 2: Create a service token with email scopes

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
}
JSON

This token can email any @example.com address and vip@partner.org, but no others. Save the returned token value.

Step 3: Send an email

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"]
}
JSON
  • toEmailstring or string[]. Required.
  • subjectstring. Required.
  • htmlstring (max 256 KB). Required.
  • ccstring[]. Optional.
  • bccstring[]. 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 }

Secrets

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:write permission cannot be granted to service tokens.
  • Only known secret store IDs are accepted (see src/schemas/secrets/index.js for 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.

PUT a secret (root/default)

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"
}
JSON

Returns 204 on success. The secret is encrypted and stored at SECRETS_BUCKET:{org}/{site}/secrets/payments-chase.json.

PUT a secret (locale-specific override)

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"
}
JSON

When code calls StorageClient.getSecrets('/ca/en/payments-chase.json'), both the root and locale secrets are fetched and merged, with locale values taking precedence.

Schemas

ProductBusEntry

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).

ProductBusPrice

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.

ProductBusMedia

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.

ProductBusOptionValue

Property Type Description
id string Optional value identifier.
value string Display value. Required.
uid string Optional stable unique identifier.

ProductBusOption

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.

ProductBusVariant

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.

AggregateRating

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.

SchemaOrgAvailability

Property Type Description
availability enum One of: BackOrder, Discontinued, InStock, InStoreOnly, LimitedAvailability, MadeToOrder, OnlineOnly, OutOfStock, PreOrder, PreSale, Reserved, SoldOut.

SchemaOrgItemCondition

Property Type Description
itemCondition enum One of: DamagedCondition, NewCondition, RefurbishedCondition, UsedCondition.

CustomObject

Property Type Description
* any Arbitrary key-value pairs. Additional properties allowed.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors