openapi: 3.2.0
info:
title: Catalog Data Ingestion Product Layers API
description: 'The Catalog Data Ingestion API allows you to create and manage products and price books and directly integrate catalog data with the Commerce catalog service.
This API provides the following resource collections to create and update catalog data:
- [Product Metadata](#tag/ProductMetadata)—define and manage product attribute metadata including display settings, search characteristics, filtering options, and sorting rules.
- [Category Metadata](#tag/CategoryMetadata)—define and manage category attribute metadata.
- [Categories](#tag/Categories)—Define and manage categories with hierarchical structure to build navigation menu.
- [Products](#tag/Products)—Define and manage catalog items with their attributes (name, description, SKU, images, and variants).
- [Price books](#tag/Price-Books)—Define and manage pricing scopes for different customer tiers and markets.
- [Prices](#tag/Prices)—Define and manage product SKU prices and their associated price books.
- [Product Layers](#tag/Product-Layers)—Define and manage product layers to customize and override base product data for specific contexts, locales, or business requirements.
'
version: 1.0.0
servers:
- url: https://na1-sandbox.api.commerce.adobe.com/{tenantId}
variables:
tenantId:
default: string
tags:
- name: Product Layers
paths:
/v1/catalog/products/layers:
post:
tags:
- Product Layers
summary: Create or replace product layers
description: "Create product layers to customize and override base product data for specific contexts, locales, or business requirements.\n\nProduct layers enable you to:\n- Override product attributes for specific markets or channels\n- Provide locale-specific content while maintaining a global base product\n- Create seasonal or promotional variations without duplicating entire product records\n- Implement A/B testing scenarios with different product presentations\n\nFor details on how to use layers with Adobe Commerce Optimizer, see\n[Catalog Layers](https://experienceleague.adobe.com/en/docs/commerce/optimizer/setup/catalog-layer) in the\nAdobe Commerce Optimizer documentation.\n\n## Layer behavior and requirements\n\n**Required fields:**\n- `sku`: Must match an existing base product SKU\n- `source.layer`: Identifies the layer name for organization and retrieval\n\n**Optional Fields:**\n- `source.locale`: When specified, layer applies only to that locale. When omitted, layer applies globally across all locales\n- All product fields (name, description, images, and so on): Override corresponding base product values\n\n## Merging logic\n\nProduct layers use intelligent merging:\n- **Simple fields** (name, description, and so on): Complete replacement of base values\n- **Array fields** (attributes, images, etc.): First-level arrays are merged with base arrays\n- **Nested arrays** (attribute.values, etc.): Complete replacement of nested arrays\n\n**Example:** Adding a color variant while preserving existing attributes:\n```json\n{\n \"sku\": \"red-pants\",\n \"source\": {\n \"locale\": \"en-US\",\n \"layer\": \"seasonal-colors\"\n },\n \"attributes\": [\n {\n \"code\": \"color\",\n \"values\": [\"Crimson Red\", \"Deep Red\"],\n \"variantReferenceId\": \"pants-color-crimson\"\n }\n ]\n}\n```\n"
operationId: createProductLayers
parameters:
- $ref: '#/components/parameters/Authorization'
- $ref: '#/components/parameters/ContentType'
- $ref: '#/components/parameters/ContentEncoding'
responses:
'200':
$ref: '#/components/responses/AcceptedResponse'
'400':
$ref: '#/components/responses/InvalidItemsResponse'
'401':
$ref: '#/components/responses/UnauthorizedResponse'
'403':
$ref: '#/components/responses/ForbiddenResponse'
'429':
$ref: '#/components/responses/TooManyRequestsResponse'
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/FeedProductLayer'
examples:
ProductLayerWithImages:
summary: Create a seasonal product layer
description: 'Create a product layer that overrides the base product with seasonal branding, localized content, and updated imagery for the US market.
'
value:
- sku: red-pants
source:
locale: en-US
layer: seasonal-winter-2024
name: Premium Red Winter Pants - Limited Edition
description: Stay warm and stylish with our premium red winter pants. Features thermal lining and water-resistant fabric perfect for cold weather adventures.
shortDescription: Premium thermal-lined winter pants in warm, classic red
images:
- url: https://cdn.example.com/products/red-pants-winter-2024.jpg
label: Premium Red Winter Pants - Front View
roles:
- BASE
- THUMBNAIL
customRoles:
- hero
- seasonal-banner
/v1/catalog/products/layers/delete:
post:
tags:
- Product Layers
summary: Delete product layers
description: 'Remove specific product layers by SKU and source identifiers. This operation permanently deletes
the layer data while preserving the base product.
**Use Cases:**
- Remove expired seasonal or promotional layers
- Clean up test layers after A/B testing completion
- Delete locale-specific layers when discontinuing market support
- Remove outdated customizations
**Important Notes:**
- Only the specified layer is deleted; base product and other layers remain intact
- Both `sku` and `source` (locale + layer) must match exactly for successful deletion
'
operationId: deleteProductLayers
parameters:
- $ref: '#/components/parameters/Authorization'
- $ref: '#/components/parameters/ContentType'
- $ref: '#/components/parameters/ContentEncoding'
responses:
'200':
$ref: '#/components/responses/AcceptedResponse'
'400':
$ref: '#/components/responses/InvalidItemsResponse'
'401':
$ref: '#/components/responses/UnauthorizedResponse'
'403':
$ref: '#/components/responses/ForbiddenResponse'
'429':
$ref: '#/components/responses/TooManyRequestsResponse'
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/FeedProductLayerDelete'
examples:
DeleteSeasonalLayer:
summary: Delete seasonal product layer
description: 'Delete a seasonal product layer after the promotion period ends, reverting the product to its base configuration.
'
value:
- sku: red-pants
source:
locale: en-US
layer: seasonal-winter-2024
components:
schemas:
FeedProductLayerDelete:
title: Catalog Product Layer delete payload
type: object
required:
- sku
- source
properties:
sku:
type: string
description: SKU (Stock Keeping Unit) that identifies the base product containing the layer to delete. Must match an existing product SKU in the catalog.
example: red-pants
source:
$ref: '#/components/schemas/SourceLayer'
ProductExternalId:
title: External Ids
type: object
required:
- id
- origin
properties:
id:
type: string
description: External ID of the product.
origin:
type: string
description: External ID origin. Specifies the system that generated the external ID, such as Adobe Commerce, Google Product Ratings, etc.
ProductAttribute:
title: Product Attribute
type: object
required:
- code
- values
properties:
code:
type: string
description: Product Attribute Code
values:
type: array
description: A list of value(s) associated with a specified attribute code.
items:
type: string
variantReferenceId:
type:
- string
- 'null'
description: 'The variant reference ID establishes a link between a product variant and the corresponding
[Option Value ID](#operation/createProducts!path=options/values/id&t=request) in a configurable product.
A variant reference ID can be specified only for a product that represents a variant of a configurable product.
'
ProductLink:
title: Links
required:
- type
- sku
type: object
properties:
type:
type: string
description: 'Product link type. Merchants can define custom types in addition to the predefined values.
- `VARIANT_OF` link type must be specified to establish a connection to the configurable product SKU.
- `IN_BUNDLE` link type must be specified to establish a connection to the bundle product SKU.
'
sku:
type: string
description: Product SKU
description: Product association
429Response:
title: 429 Too Many Requests
description: 'Too many requests. Indicates that a client has exceeded the rate limit of 300 requests per minute.
Check the `retry-after` header to get the time (in seconds) to wait before sending the next request.
'
type: string
ProductMetaAttribute:
title: Meta Attributes
description: Meta attributes that are specified in tags.
type: object
properties:
title:
type: string
description: A meta title
keywords:
type: array
description: A meta keywords
items:
type: string
description:
type: string
description: A meta description
403Response:
title: 403 Forbidden
type: object
properties:
title:
type: string
description: Error title
status:
type: string
description: Error status code
error_code:
type: string
description: Error code
message:
type: string
description: Error message
example:
title: ErrMissingOauthToken
status: '403'
error_code: '403010'
message: Oauth token is missing
400ProcessFeedResponse:
title: Response payload
type: object
properties:
status:
type: string
description: Request status.
default: FAILED
message:
type: string
description: Error summary.
errors:
type: array
description: List of items that did not pass validation. Fix the payload for invalid items before resubmitting the request.
items:
$ref: '#/components/schemas/FeedItemFailedValidationResult'
example:
status: FAILED
message: Items validation failed for 2 items
errors:
- itemIndex: 0
code: status
message: 'status: does not have a value in the enumeration ["ENABLED", "DISABLED"]'
value: active
- itemIndex: 1
code: source
message: required property 'source' not found
value: ''
401Response:
title: 401 Unauthorized
type: object
properties:
title:
type: string
description: Error title
status:
type: string
description: Error status code
error_code:
type: string
description: Error code
message:
type: string
description: Error message
example:
title: ErrInvalidOauthToken
status: '401'
error_code: '401013'
message: Oauth token is not valid
FeedItemFailedValidationResult:
title: FeedItemFailedValidationResult
type: object
properties:
code:
type: string
description: Code name of invalid field.
itemIndex:
type: integer
format: int32
description: Reference to the line item with an invalid payload. The line count begins at 0.
message:
type: string
description: Error description
value:
type: string
description: Original value passed in the request.
ProcessFeedResponse:
title: Response payload
type: object
properties:
status:
type: string
description: Request status.
default: ACCEPTED
acceptedCount:
type: integer
description: The number of received and accepted items.
format: int32
example:
status: ACCEPTED
acceptedCount: 4
FeedProductLayer:
title: Catalog Product Layer payload
type: object
required:
- sku
- source
properties:
sku:
type: string
description: SKU (Stock Keeping Unit) that uniquely identifies the base product this layer will modify. Must match an existing product SKU in the catalog.
example: red-pants
source:
$ref: '#/components/schemas/SourceLayer'
name:
type: string
description: Product display name that will override the base product name. Use for localized names, seasonal branding, or promotional titles.
example: Premium Red Winter Pants - Limited Edition
description:
type:
- string
- 'null'
description: Detailed product description that replaces the base product description. Use for localized content, seasonal messaging, or enhanced marketing copy.
example: Stay warm and stylish with our premium red winter pants. Features thermal lining and water-resistant fabric perfect for cold weather adventures.
shortDescription:
type:
- string
- 'null'
description: Brief product summary that appears in product listings and search results. Override for concise, layer-specific messaging.
example: Premium thermal-lined winter pants in classic red
metaTags:
$ref: '#/components/schemas/ProductMetaAttribute'
attributes:
type: array
description: Product attributes that will be merged with base product attributes. Use to add layer-specific variants, localized values, or seasonal properties.
items:
$ref: '#/components/schemas/ProductAttribute'
images:
type: array
description: Product images that will be merged with base product images. Use to add seasonal imagery, locale-specific photos, or promotional visuals.
items:
$ref: '#/components/schemas/ProductImage'
links:
type: array
description: Related product SKUs that will be merged with base product links. Use to add seasonal recommendations, locale-specific cross-sells, or promotional bundles.
items:
$ref: '#/components/schemas/ProductLink'
externalIds:
type: array
description: External system identifiers that will be merged with base product external IDs. Use to add layer-specific tracking codes, campaign IDs, or integration references.
items:
$ref: '#/components/schemas/ProductExternalId'
ProductImage:
title: Product Image
type: object
required:
- url
properties:
url:
type: string
description: Media resource URL
label:
type: string
description: Media resource label
roles:
type: array
description: 'Roles associated with this image that determine how the image is used on the storefront.
- `BASE`: Product image is visible as a main image on the Product Detail Page.
- `SMALL`: Product image is visible as a main image on the Category or search result page or other product listing pages.
- `THUMBNAIL`: Thumbnail images appear in the thumbnail gallery, shopping cart, etc.
- `SWATCH`: A swatch can be used to illustrate the color, pattern, or texture.
'
items:
enum:
- BASE
- SMALL
- THUMBNAIL
- SWATCH
customRoles:
type: array
description: 'Custom image role. Merchants can define custom roles in addition to the predefined values.
'
items:
type: string
SourceLayer:
title: Catalog layer source
description: "Identifies the source context for a product layer, combining locale and layer name to create \na unique layer identifier. This allows for precise targeting of content overrides.\n"
type: object
required:
- layer
properties:
locale:
type: string
description: "ISO locale code (for example, \"en-US\", \"fr-FR\", \"de-DE\") that specifies the target market or language. \nWhen omitted, the layer applies globally across all locales. Use for market-specific customizations.\n"
example: en-US
layer:
type: string
description: "Unique identifier for the layer within the product's layer hierarchy. Use descriptive names \nthat indicate the layer's purpose (for example, \"seasonal-winter-2024\", \"promotional-black-friday\", \"a-b-test-variant\").\n"
example: seasonal-winter-2024
parameters:
ContentType:
name: Content-Type
in: header
required: true
schema:
type: string
enum:
- application/json
default: application/json
ContentEncoding:
name: Content-Encoding
in: header
required: false
schema:
type: string
enum:
- gzip
description: Use this header if the payload is compressed with gzip.
Authorization:
name: Authorization
in: header
required: true
schema:
type: string
description: Authorization Bearer token
responses:
UnauthorizedResponse:
x-summary: Unauthorized request
description: 'Verify that the Bearer token provided in the `Authorization` header is still valid.
'
content:
application/json;charset=UTF-8:
schema:
$ref: '#/components/schemas/401Response'
InvalidItemsResponse:
x-summary: Request rejected
description: 'Some of the received items are invalid. Check the "message" and "errors" fields for details.
Common causes of validation errors include:
* **Invalid SKU**: SKU does not exist in the catalog
* **Invalid Price Book**: Price book ID does not exist
* **Invalid Discount Code**: Duplicate or invalid discount codes
* **Invalid Tier Quantities**: Quantities not in ascending order or less than 2
* **Configurable Product Price**: Attempting to set price for configurable product SKU
* **Invalid Price Format**: Non-numeric or negative price values
* **Incorrect Category Slug**: Invalid category slug format
* **Incorrect hierarchy configuration**: Misconfiguration of price book parent-child relationship
'
content:
application/json;charset=UTF-8:
schema:
$ref: '#/components/schemas/400ProcessFeedResponse'
ForbiddenResponse:
x-summary: Forbidden request
description: 'Verify that the `Authorization` header is present, and that the Bearer token is still valid.
'
content:
application/json;charset=UTF-8:
schema:
$ref: '#/components/schemas/403Response'
TooManyRequestsResponse:
x-summary: Too many requests
description: 'Indicates that a client has exceeded the rate limit of 300 requests per minute.
Check the `retry-after` header to get the time (in seconds) to wait before sending the next request.
'
content:
text/html;charset=UTF-8:
schema:
$ref: '#/components/schemas/429Response'
AcceptedResponse:
x-summary: All items accepted
description: 'All items accepted and will be processed asynchronously
'
content:
application/json;charset=UTF-8:
schema:
$ref: '#/components/schemas/ProcessFeedResponse'
externalDocs:
url: https://github.com/adobe-commerce/aco-ts-sdk/blob/main/README.md
description: Learn about the Adobe Commerce Optimizer TypeScript and JavaScript SDK for Merchandising Services